diff --git a/docs/SDKs/quote-ruby.md b/docs/SDKs/quote-ruby.md index a5d7427d..5d874a79 100644 --- a/docs/SDKs/quote-ruby.md +++ b/docs/SDKs/quote-ruby.md @@ -911,6 +911,78 @@ puts result["quote"]["id"] --- +### Sorting, filters and the list summary + +Every list takes `sortBy` / `sortDirection` (`asc` | `desc`); leave them out for the list's usual order. + +| List | `sortBy` values | Order without a sort | +|---|---|---| +| Quotes | `updatedOn`, `createdOn`, `total` (grand total), `validUntil`, `quoteNumber` | Newest created first | +| Products | `name`, `listPrice`, `createdOn` | Newest first | +| Price books | `name`, `discountPercent`, `overrideCount`, `validFrom`, `validTo`, `createdOn` | Newest first | +| Bundles | `name`, `itemCount`, `totalListPrice`, `totalFinalPrice`, `createdOn` | Newest first | +| Companies | `name`, `contactCount`, `lastActivityDate` | Most recently active first | +| Contacts (both lists) | `name`, `createdOn` | Newest first | +| Types | `name`, `usageCount` (needs `categoryType`) | Name, A to Z | + +Quote list filters (one value or an array): + +| Filter | Values | Notes | +|---|---|---| +| `statuses` | `draft`, `sent`, `accepted`, `declined`, `voided`, **`expired`** | `expired` = a draft or sent quote past its Valid until day (UTC), or whose signature expired. It's a filter value, not a stored status. | +| `companyId` / `companyIds` | One company, or several | Merged by the API | +| `currency` / `currencies` | One currency, or several | Merged by the API | +| `createdBy` | User IDs | From `listQuoteCreators` | +| `createdByApiKeys` | `true` | Quotes created by any API key (combined with `createdBy`) | +| `validUntilWindow` | `thisWeek` (today + 6 days), `thisMonth`, `past` | UTC days | +| `validUntilFrom` / `validUntilTo` | `YYYY-MM-DD` | Inclusive; combined with the window | +| `summaryCurrency` | A currency | The currency of `summary` (default: the one filtered currency, else USD) | + +The response adds `statusCounts` and `summary`; each quote carries `isExpired`, `isSignatureExpired` and `lineItemCount`. In the other lists, each price book carries `overrideCount`, each bundle carries `itemCount` and `billingTotals` (the bundle price per billing type, for example `{ "one-time" => 1538.73, "monthly" => 11.27 }`), and each company carries `contactCount`. + +```ruby +page = TurboDocxSdk::TurboQuote.list_quotes( + "statuses" => %w[sent expired], + "currencies" => %w[USD EUR], + "validUntilWindow" => "thisMonth", + "sortBy" => "validUntil", + "sortDirection" => "asc", + "summaryCurrency" => "USD" +) +puts page["statusCounts"]["expired"], page["summary"]["winRate"]["percent"] + +creators = TurboDocxSdk::TurboQuote.list_quote_creators # ids for createdBy +summary = TurboDocxSdk::TurboQuote.get_quote_summary("createdBy" => [creators.first["id"]]) +next_number = TurboDocxSdk::TurboQuote.get_next_quote_number # read only + +copy = TurboDocxSdk::TurboQuote.duplicate_quote(quote["id"], name: "Q4 renewal") # name is optional +``` + +`duplicate_quote`, `duplicate_product`, `duplicate_price_book` and `duplicate_bundle` take an optional +`name:` (otherwise "Copy of …"). Companies take an optional `"email"`; `update_price_book(id, "resetProductPricing" => true)` +puts every product back on the book's discount. + +### Custom line item images + +A custom line item (one with no catalog product) can show up to three images on the quote (PNG or +JPEG, 2 MB each; draft quotes only). Catalog products use `get_product_quote_images(product_ids)`. + +```ruby +images = TurboDocxSdk::TurboQuote.add_line_item_images(quote["id"], item_id, ["./diagram.png"]) # paths or IO objects +TurboDocxSdk::TurboQuote.reorder_line_item_images(quote["id"], item_id, images.map { |i| i["id"] }.reverse) +TurboDocxSdk::TurboQuote.remove_line_item_image(quote["id"], item_id, images.first["id"]) +by_item = TurboDocxSdk::TurboQuote.get_quote_line_item_images(quote["id"]) # { line_item_id => [image, ...] } +``` + +**Deletes the API refuses.** `delete_quote` on a **sent** quote is a 409 `ConflictError` with code +`CANNOT_DELETE_SENT_QUOTE` — void it instead; an accepted quote is a 409 `CANNOT_DELETE_ACCEPTED_QUOTE`. +`delete_company` is a 409 `CompanyHasOpenQuotes` while the company has open quotes (draft or +sent), and `delete_contact` is a 409 `LastContact` (the company's only contact) or `ContactHasOpenQuotes`. +`delete_price_book` on the org's default price book is a 400 `ValidationError` `PriceBookIsDefault`. Branch on +`e.code`; `get_company_open_quotes` / `get_contact_open_quotes` list the open quotes that block a delete. + +Also: `get_next_quote_number` (the number the next quote will get, read only), `get_product_quote_images(product_ids)` (up to three images per product; products hold at most three), `email` on companies, `"resetProductPricing" => true` on `update_price_book`. + ## Constants The gem exposes constants so you can avoid hard-coding string literals: @@ -973,6 +1045,26 @@ end --- +### TurboQuote error codes + +Every typed error carries the API's `code` (`err.code`, `e.code`, `$e->errorCode`, `err.Code`, `e.getCode()`). The codes you're most likely to branch on: + +| Status | Code | When | +|---|---|---| +| 409 | `CANNOT_DELETE_SENT_QUOTE` | Deleting a sent quote. Void it instead. | +| 409 | `CANNOT_DELETE_ACCEPTED_QUOTE` | Deleting an accepted quote. It's kept for your records. | +| 409 | `CompanyHasOpenQuotes` | Deleting a company that has open quotes (draft or sent). See `getCompanyOpenQuotes`. | +| 409 | `ContactHasOpenQuotes` | Deleting a contact who is on open quotes. See `getContactOpenQuotes`. | +| 409 | `LastContact` | Deleting a company's only contact. | +| 400 | `PriceBookIsDefault` | Deleting the organization's default price book. | +| 400 | `MAX_IMAGES_EXCEEDED` | More than three images on a product or custom line item. | +| 400 | `IMAGE_TOO_LARGE` / `INVALID_FILE_TYPE` | An image over 2 MB, or not PNG / JPEG. | +| 400 | `QUOTE_NOT_EDITABLE` | Changing a quote (or its line items or images) that isn't a draft. | +| 404 | `QUOTE_NOT_FOUND`, `LINE_ITEM_NOT_FOUND`, `IMAGE_NOT_FOUND` | The quote, line item or image doesn't exist in your organization. | +| 400 | `SenderEmailRequired` | An API-key caller whose quote template has no sender email. | + +Money fields are capped at 9,999,999,999,999.99, quantities at 2,147,483,647 and percents at 999.99 (a percent discount at 100); a larger value is a 400 with the field named. An amount discount larger than the price it comes off is a 400. + ## See Also - [TurboQuote JavaScript / TypeScript SDK](/docs/SDKs/quote-javascript) — same API, JS idioms diff --git a/docs/SDKs/quote.md b/docs/SDKs/quote.md index 43ee63ae..93d85773 100644 --- a/docs/SDKs/quote.md +++ b/docs/SDKs/quote.md @@ -69,7 +69,7 @@ The official TurboDocx TurboQuote SDK for Node.js and browser applications. Buil
:::info What is TurboQuote? -TurboQuote is TurboDocx's quoting and CPQ module. Quotes progress through a lifecycle: `draft` → `pending_approval` → `sent` → `accepted` / `declined` / `voided`. A `draft` can also be marked `declined` directly, for a deal that dies before the quote is ever sent. Each quote belongs to a company and contact, carries line items (individual products or bundles), and can optionally have a price book applied. Accepted quotes can be merged with a TurboDocx Deliverable (e.g. a contract generated from a template) and sent for e-signature through TurboSign via `sendQuoteWithDeliverable`. +TurboQuote is TurboDocx's quoting and CPQ module. Quotes progress through a lifecycle: `draft` → `sent` → `accepted` / `declined` / `voided`. A `draft` can also be marked `declined` directly, for a deal that dies before the quote is ever sent. Each quote belongs to a company and contact, carries line items (individual products or bundles), and can optionally have a price book applied. Accepted quotes can be merged with a TurboDocx Deliverable (e.g. a contract generated from a template) and sent for e-signature through TurboSign via `sendQuoteWithDeliverable`. ::: @@ -1190,6 +1190,223 @@ list.getResults().forEach(q -> +#### Sorting and filtering lists {#sorting-and-filtering-lists} + +Every TurboQuote list takes `sortBy` and `sortDirection` (`asc` | `desc`). Leave them out and the list keeps the order it has always had. + +| List | `sortBy` values | Order without a sort | +|---|---|---| +| Quotes | `updatedOn`, `createdOn`, `total` (grand total), `validUntil`, `quoteNumber` | Newest created first | +| Products | `name`, `listPrice`, `createdOn` | Newest first | +| Price books | `name`, `discountPercent`, `overrideCount`, `validFrom`, `validTo`, `createdOn` | Newest first | +| Bundles | `name`, `itemCount`, `totalListPrice`, `totalFinalPrice`, `createdOn` | Newest first | +| Companies | `name`, `contactCount`, `lastActivityDate` | Most recently active first | +| Contacts (both lists) | `name`, `createdOn` | Newest first | +| Types | `name`, `usageCount` (needs `categoryType`) | Name, A to Z | + +The quote list also takes these filters. Multi-value filters take one value or a list (sent as repeated query parameters): + +| Filter | Values | Notes | +|---|---|---| +| `statuses` | `draft`, `sent`, `accepted`, `declined`, `voided`, **`expired`** | `expired` = a draft or sent quote past its Valid until day (UTC), or whose signature expired. It's a filter value, not a stored status. | +| `companyId` / `companyIds` | One company, or several | Merged by the API | +| `currency` / `currencies` | One currency, or several | Merged by the API | +| `createdBy` | User IDs | From `listQuoteCreators` | +| `createdByApiKeys` | `true` | Quotes created by any API key (combined with `createdBy`) | +| `validUntilWindow` | `thisWeek` (today + 6 days), `thisMonth`, `past` | UTC days | +| `validUntilFrom` / `validUntilTo` | `YYYY-MM-DD` | Inclusive; combined with the window | +| `summaryCurrency` | A currency | The currency of `summary` (default: the one filtered currency, else USD) | + +Each quote in the list carries `isExpired` (the same rule as the `expired` filter), `isSignatureExpired` and `lineItemCount`. Next to `results`, `totalRecords` and `stats`, the response carries `statusCounts` (how many quotes each status tab would hold, with every filter except `statuses`) and `summary` (the summary cards below, in `summaryCurrency`). Products also filter by several `billingFrequency` and `currency` values, bundles by several `currency` values, and contacts by several `companyIds`. In the other lists, each price book carries `overrideCount` (how many products have their own price in it), each bundle carries `itemCount` and `billingTotals` (the bundle price per billing type, for example `{ "one-time": 1538.73, "monthly": 11.27 }`, with the bundle discount shared across them), and each company carries `contactCount`. + + + + +```typescript +const page = await TurboQuote.listQuotes({ + statuses: ['sent', 'expired'], + currencies: ['USD', 'EUR'], + validUntilWindow: 'thisMonth', + sortBy: 'validUntil', + sortDirection: 'asc', + summaryCurrency: 'USD', +}); +// page.statusCounts → { all, draft, sent, accepted, declined, voided, expired } +// page.summary → { openPipeline, winRate, monthlyRecurring, ... } in USD +for (const q of page.results) { + console.log(q.quoteNumber, q.isExpired, q.lineItemCount); +} + +const products = await TurboQuote.listProducts({ billingFrequency: ['monthly', 'annual'], sortBy: 'listPrice', sortDirection: 'desc' }); +``` + + + + +```python +page = await TurboQuote.list_quotes({ + "statuses": ["sent", "expired"], + "currencies": ["USD", "EUR"], + "validUntilWindow": "thisMonth", + "sortBy": "validUntil", + "sortDirection": "asc", + "summaryCurrency": "USD", +}) +print(page["statusCounts"]["expired"], page["summary"]["winRate"]["percent"]) +for q in page["results"]: + print(q["quoteNumber"], q["isExpired"], q["lineItemCount"]) + +products = await TurboQuote.list_products({"billingFrequency": ["monthly", "annual"], "sortBy": "listPrice", "sortDirection": "desc"}) +``` + + + + +```php +use TurboDocx\Types\Requests\Quote\ListQuotesRequest; +use TurboDocx\Types\Requests\Quote\ListProductsRequest; + +$page = TurboQuote::listQuotes(new ListQuotesRequest( + statuses: ['sent', 'expired'], + currencies: ['USD', 'EUR'], + validUntilWindow: 'thisMonth', + sortBy: 'validUntil', + sortDirection: 'asc', + summaryCurrency: 'USD', +)); +echo $page->statusCounts?->expired, ' ', $page->summary?->winRate['percent']; +foreach ($page->results as $q) { + echo "{$q->quoteNumber} expired=" . var_export($q->isExpired, true) . "\n"; +} + +$products = TurboQuote::listProducts(new ListProductsRequest(billingFrequency: ['monthly', 'annual'], sortBy: 'listPrice', sortDirection: 'desc')); +``` + + + + +```go +str := func(s string) *string { return &s } + +page, err := qc.ListQuotes(ctx, &turbodocx.ListQuotesOptions{ + Statuses: []string{"sent", turbodocx.QuoteListStatusExpired}, + Currencies: []string{"USD", "EUR"}, + ValidUntilWindow: str(turbodocx.ValidUntilThisMonth), + SortBy: str(turbodocx.QuoteSortByValidUntil), + SortDirection: str(turbodocx.SortAsc), + SummaryCurrency: str("USD"), +}) +fmt.Println(page.StatusCounts.Expired, page.Summary.WinRate.Percent) + +// Several values for a key that also takes one: BillingFrequencies / CurrencyCodes +products, err := qc.ListProducts(ctx, &turbodocx.ListProductsOptions{ + BillingFrequencies: []string{"monthly", "annual"}, + SortBy: str("listPrice"), + SortDirection: str(turbodocx.SortDesc), +}) +``` + + + + +```java +ListQuotesOptions opts = new ListQuotesOptions(); +opts.setStatuses(Arrays.asList("sent", "expired")); +opts.setCurrencies(Arrays.asList("USD", "EUR")); +opts.setValidUntilWindow("thisMonth"); +opts.setSortBy("validUntil"); +opts.setSortDirection("asc"); +opts.setSummaryCurrency("USD"); + +QuoteListResponse page = tq.listQuotes(opts); +System.out.println(page.getStatusCounts().getExpired() + " " + page.getSummary().getWinRate().getPercent()); + +ListProductsOptions products = new ListProductsOptions(); +products.setBillingFrequencies(Arrays.asList("monthly", "annual")); +products.setSortBy("listPrice"); +products.setSortDirection("desc"); +tq.listProducts(products); +``` + + + + +#### `getQuoteSummary` / `get_quote_summary` / GetQuoteSummary and `listQuoteCreators` {#getquotesummary} + +`getQuoteSummary` returns the quote list's summary cards for a set of filters, in one currency: the open pipeline (draft and sent quotes that aren't expired), accepted and declined counts, quotes created and won this month, quotes waiting to be signed, the win rate over the last 90 days (`percent` is `null` when none were decided) and the monthly recurring total of accepted quotes. It takes the same filters as `listQuotes`, except `statuses` (the cards split quotes by status themselves) and the currency list (the cards are in `summaryCurrency`). + +`listQuoteCreators` lists the people and API keys who created the organization's quotes. Use their `id` in the `createdBy` filter, for example for a per-rep report. + + + + +```typescript +const summary = await TurboQuote.getQuoteSummary({ currencies: ['EUR'], summaryCurrency: 'EUR' }); +// { currency, openPipeline: { total, count }, completed: { accepted, declined }, +// createdThisMonth, waitingToSign, wonThisMonth, currencies, +// winRate: { percent | null, accepted, declined, windowDays }, monthlyRecurring: { total, count } } + +const creators = await TurboQuote.listQuoteCreators(); +// [{ id, name, email | null, isAPIKey, apiKeyDeleted }] — use id in the createdBy filter +const mine = await TurboQuote.listQuotes({ createdBy: [creators[0].id] }); +``` + + + + +```python +summary = await TurboQuote.get_quote_summary({"currencies": ["EUR"], "summaryCurrency": "EUR"}) +print(summary["openPipeline"]["total"], summary["winRate"]["percent"]) + +creators = await TurboQuote.list_quote_creators() +# [{"id", "name", "email" (None for an API key), "isAPIKey", "apiKeyDeleted"}] +mine = await TurboQuote.list_quotes({"createdBy": [creators[0]["id"]]}) +``` + + + + +```php +use TurboDocx\Types\Requests\Quote\QuoteSummaryRequest; + +$summary = TurboQuote::getQuoteSummary(new QuoteSummaryRequest(currencies: ['EUR'], summaryCurrency: 'EUR')); +echo $summary->openPipeline['total'], ' ', $summary->winRate['percent'] ?? 'n/a'; + +$creators = TurboQuote::listQuoteCreators(); // QuoteCreator[]: id, name, email (null for an API key), isAPIKey, apiKeyDeleted +$mine = TurboQuote::listQuotes(new ListQuotesRequest(createdBy: [$creators[0]->id])); +``` + + + + +```go +summary, err := qc.GetQuoteSummary(ctx, &turbodocx.QuoteSummaryOptions{ + Currencies: []string{"EUR"}, + SummaryCurrency: str("EUR"), +}) +fmt.Println(summary.OpenPipeline.Total, summary.WinRate.Percent) // Percent is nil when none were decided + +creators, err := qc.ListQuoteCreators(ctx) // []QuoteCreator: ID, Name, Email (nil for an API key), IsAPIKey, APIKeyDeleted +mine, err := qc.ListQuotes(ctx, &turbodocx.ListQuotesOptions{CreatedBy: []string{creators[0].ID}}) +``` + + + + +```java +QuoteSummaryOptions filters = new QuoteSummaryOptions(); +filters.setCurrencies(Arrays.asList("EUR")); +filters.setSummaryCurrency("EUR"); +QuoteSummary summary = tq.getQuoteSummary(filters); +System.out.println(summary.getOpenPipeline().getTotal() + " " + summary.getWinRate().getPercent()); + +List creators = tq.listQuoteCreators(); // getName(), getEmail() (null for an API key), getIsAPIKey() +``` + + + + + #### `createQuote` / `create_quote` / CreateQuote {#createquote} @@ -1611,10 +1828,54 @@ System.out.println(resp.getMessage()); +:::caution Deletes the API refuses +A **sent** quote can't be deleted: void it instead (409, code `CANNOT_DELETE_SENT_QUOTE`). An accepted quote can't be deleted either (409, `CANNOT_DELETE_ACCEPTED_QUOTE`). Drafts and declined or voided quotes can be deleted. +::: + #### `duplicateQuote` / `duplicate_quote` / DuplicateQuote {#duplicatequote} +Takes an optional name for the copy; without one the copy is called "Copy of …". Custom line items keep their images. + + + + +```typescript +const copy = await TurboQuote.duplicateQuote(quoteId, { name: 'Acme renewal 2027' }); // name is optional +``` + + + + +```python +copy = await TurboQuote.duplicate_quote(quote_id, name="Acme renewal 2027") # name is optional +``` + + + + +```php +$copy = TurboQuote::duplicateQuote($quoteId, 'Acme renewal 2027'); // name is optional +``` + + + + +```go +copy, err := qc.DuplicateQuote(ctx, quoteID, turbodocx.DuplicateOptions{Name: "Acme renewal 2027"}) // options are optional +``` + + + + +```java +Quote copy = tq.duplicateQuote(quoteId, "Acme renewal 2027"); // or duplicateQuote(quoteId) +``` + + + + @@ -2068,6 +2329,48 @@ System.out.println(config.getFormat().getStartNumber()); // 1000 +#### `getNextQuoteNumber` / `get_next_quote_number` / GetNextQuoteNumber {#getnextquotenumber} + +The number the next new quote will get, for showing before a quote is created. It's read only: the counter doesn't move, so a quote created by someone else in between takes that number first. Any role that can create quotes may call it; `canEdit` says whether the caller can change numbering (administrators). + + + + +```typescript +const { nextNumber, sequence, canEdit } = await TurboQuote.getNextQuoteNumber(); +``` + + + + +```python +nxt = await TurboQuote.get_next_quote_number() # {"nextNumber", "sequence", "canEdit"} +``` + + + + +```php +$next = TurboQuote::getNextQuoteNumber(); // ->nextNumber, ->sequence, ->canEdit +``` + + + + +```go +next, err := qc.GetNextQuoteNumber(ctx) // next.NextNumber, next.Sequence, next.CanEdit +``` + + + + +```java +NextQuoteNumber next = tq.getNextQuoteNumber(); // getNextNumber(), getSequence(), getCanEdit() +``` + + + + #### Field reference, defaults & validation {#field-reference-defaults--validation} @@ -3405,6 +3708,73 @@ tq.removeLineItem(quoteId, itemId); +### Custom Line Item Images {#custom-line-item-images} + +A custom line item (a line with `productId: null`) can show up to **three** images on the quote preview and PDF, side by side in order, like a catalog product. Images are PNG or JPEG, 2 MB each, and can only be changed while the quote is a draft. Each call returns the line item's images after the change. Duplicating a quote copies them. + +| Method | HTTP | +|---|---| +| `getQuoteLineItemImages(quoteId)` | GET `/v1/quotes/{id}/items/images` — every custom item's images, keyed by line item ID | +| `getLineItemImages(quoteId, itemId)` | GET `/v1/quotes/{id}/items/{itemId}/images` | +| `addLineItemImages(quoteId, itemId, images)` | POST `/v1/quotes/{id}/items/{itemId}/images` (multipart `images` parts) | +| `reorderLineItemImages(quoteId, itemId, imageIds)` | PUT `/v1/quotes/{id}/items/{itemId}/images/order` | +| `removeLineItemImage(quoteId, itemId, imageId)` | DELETE `/v1/quotes/{id}/items/{itemId}/images/{imageId}` | + + + + +```typescript +const images = await TurboQuote.addLineItemImages(quoteId, itemId, ['./diagram.png', jpegBuffer]); // paths, Buffers or Files +await TurboQuote.reorderLineItemImages(quoteId, itemId, [images[1].id, images[0].id]); // first to last +const left = await TurboQuote.removeLineItemImage(quoteId, itemId, images[0].id); // the images left +const one = await TurboQuote.getLineItemImages(quoteId, itemId); +const byItem = await TurboQuote.getQuoteLineItemImages(quoteId); // { [lineItemId]: LineItemImage[] } +``` + + + + +```python +images = await TurboQuote.add_line_item_images(quote_id, item_id, ["./diagram.png"]) # paths, bytes or files +await TurboQuote.reorder_line_item_images(quote_id, item_id, [images[1]["id"], images[0]["id"]]) +left = await TurboQuote.remove_line_item_image(quote_id, item_id, images[0]["id"]) +by_item = await TurboQuote.get_quote_line_item_images(quote_id) # {line_item_id: [image, ...]} +``` + + + + +```php +$images = TurboQuote::addLineItemImages($quoteId, $itemId, ['/path/to/diagram.png']); // paths or raw bytes +TurboQuote::reorderLineItemImages($quoteId, $itemId, [$images[1]->id, $images[0]->id]); +$left = TurboQuote::removeLineItemImage($quoteId, $itemId, $images[0]->id); +$byItem = TurboQuote::getQuoteLineItemImages($quoteId); // [lineItemId => LineItemImage[]] +``` + + + + +```go +images, err := qc.AddLineItemImages(ctx, quoteID, itemID, []turbodocx.ProductImageInput{{FilePath: "./diagram.png"}}) +_, err = qc.ReorderLineItemImages(ctx, quoteID, itemID, []string{images[1].ID, images[0].ID}) +left, err := qc.RemoveLineItemImage(ctx, quoteID, itemID, images[0].ID) +byItem, err := qc.GetQuoteLineItemImages(ctx, quoteID) // map[lineItemID][]LineItemImage +``` + + + + +```java +List images = tq.addLineItemImages(quoteId, itemId, + new byte[][]{Files.readAllBytes(Paths.get("diagram.png"))}); +tq.reorderLineItemImages(quoteId, itemId, Arrays.asList(images.get(1).getId(), images.get(0).getId())); +List left = tq.removeLineItemImage(quoteId, itemId, images.get(0).getId()); +Map> byItem = tq.getQuoteLineItemImages(quoteId); +``` + + + + ### Products {#products} @@ -3705,6 +4075,48 @@ if img, ok := images["product-uuid-1"]; ok && img != nil { +#### `getProductQuoteImages` / `get_product_quote_images` / GetProductQuoteImages {#getproductquoteimages} + +A product holds up to **three** images (PNG or JPEG, 2 MB each); adding a fourth is a 400 `MAX_IMAGES_EXCEEDED`. A product that already has more keeps them until an image is added, and a duplicate copies the first three. `getProductQuoteImages` returns the images each product shows on a quote — up to three, in order (an empty list when none) — for 1 to 100 product IDs. `getProductPrimaryImages` still returns only the first image of each. + + + + +```typescript +const images = await TurboQuote.getProductQuoteImages(['product-uuid-1', 'product-uuid-2']); // { [productId]: ProductImage[] } +``` + + + + +```python +images = await TurboQuote.get_product_quote_images(["product-uuid-1", "product-uuid-2"]) +``` + + + + +```php +$images = TurboQuote::getProductQuoteImages(['product-uuid-1', 'product-uuid-2']); +``` + + + + +```go +images, err := qc.GetProductQuoteImages(ctx, []string{"product-uuid-1", "product-uuid-2"}) // map[productID][]ProductImage +``` + + + + +```java +Map> images = tq.getProductQuoteImages(Arrays.asList("product-uuid-1", "product-uuid-2")); +``` + + + + ### Bundles {#bundles} @@ -4133,6 +4545,51 @@ System.out.println("Products: " + pbProducts.getTotalRecords()); +#### Reset product pricing and the default price book {#reset-product-pricing} + +`updatePriceBook` takes `resetProductPricing: true` to put every product of the book back on the book's own discount (applied before any `productPricing` in the same request). Leaving `isDefault` out of an update no longer clears it. The organization's default price book can't be deleted (400 `PriceBookIsDefault`): make another book the default first. Duplicates of products, price books and bundles take an optional name, like `duplicateQuote`. + + + + +```typescript +await TurboQuote.updatePriceBook(priceBookId, { resetProductPricing: true }); +``` + + + + +```python +await TurboQuote.update_price_book(price_book_id, {"resetProductPricing": True}) +``` + + + + +```php +TurboQuote::updatePriceBook($priceBookId, new UpdatePriceBookRequest(resetProductPricing: true)); +``` + + + + +```go +yes := true +_, err := qc.UpdatePriceBook(ctx, priceBookID, &turbodocx.UpdatePriceBookRequest{ResetProductPricing: &yes}) +``` + + + + +```java +UpdatePriceBookRequest req = new UpdatePriceBookRequest(); +req.setResetProductPricing(true); +tq.updatePriceBook(priceBookId, req); +``` + + + + ### Companies {#companies} @@ -4306,6 +4763,62 @@ String contactId = contacts.getResults().get(0).getId(); +#### Company email and `getCompanyOpenQuotes` {#getcompanyopenquotes} + +Companies have an optional `email` (the company's own address) on create, update and bulk import; it's returned on every company. A company can't be deleted while it has open quotes — draft or sent (409 `CompanyHasOpenQuotes`); accepted, declined and voided quotes don't block it. `getCompanyOpenQuotes` returns those quotes (`{ results, totalRecords }`, the newest 50) so you can check before deleting. `listCompanyContacts` returns `company.contactCount`, the company's active contacts whatever the search. + + + + +```typescript +const open = await TurboQuote.getCompanyOpenQuotes(companyId); // { results, totalRecords } +if (open.totalRecords === 0) { + await TurboQuote.deleteCompany(companyId); +} +``` + + + + +```python +open_quotes = await TurboQuote.get_company_open_quotes(company_id) +if open_quotes["totalRecords"] == 0: + await TurboQuote.delete_company(company_id) +``` + + + + +```php +$open = TurboQuote::getCompanyOpenQuotes($companyId); +if ($open->totalRecords === 0) { + TurboQuote::deleteCompany($companyId); +} +``` + + + + +```go +open, err := qc.GetCompanyOpenQuotes(ctx, companyID) +if err == nil && open.TotalRecords == 0 { + _, err = qc.DeleteCompany(ctx, companyID) +} +``` + + + + +```java +OpenQuotesResponse open = tq.getCompanyOpenQuotes(companyId); +if (open.getTotalRecords() == 0) { + tq.deleteCompany(companyId); +} +``` + + + + ### Contacts {#contacts} @@ -4448,6 +4961,48 @@ Contact contact = tq.createContact(req); +#### `getContactOpenQuotes` / `get_contact_open_quotes` / GetContactOpenQuotes {#getcontactopenquotes} + +A contact can't be deleted while they're the contact on open quotes (409 `ContactHasOpenQuotes`), or when they're the company's only contact (409 `LastContact`; a company always keeps at least one). `getContactOpenQuotes` returns the open quotes made out to the contact. + + + + +```typescript +const open = await TurboQuote.getContactOpenQuotes(contactId); // { results, totalRecords } +``` + + + + +```python +open_quotes = await TurboQuote.get_contact_open_quotes(contact_id) +``` + + + + +```php +$open = TurboQuote::getContactOpenQuotes($contactId); +``` + + + + +```go +open, err := qc.GetContactOpenQuotes(ctx, contactID) +``` + + + + +```java +OpenQuotesResponse open = tq.getContactOpenQuotes(contactId); +``` + + + + ### Quote Templates {#quote-templates} @@ -5211,7 +5766,7 @@ The other five bulk methods follow the exact same pattern: | Type | Values | |---|---| -| `QuoteStatus` | `draft`, `pending_approval`, `sent`, `accepted`, `declined`, `voided` | +| `QuoteStatus` | `draft`, `sent`, `accepted`, `declined`, `voided` | | `BillingFrequency` | `monthly`, `quarterly`, `annual`, `one-time` | | `LineItemType` | `product`, `bundle` | | `RenewalPeriod` | `weekly`, `monthly`, `quarterly`, `annually` | @@ -5446,7 +6001,7 @@ import type { | Type | Values | |---|---| -| `QuoteStatus` | `'draft'` `'pending_approval'` `'sent'` `'accepted'` `'declined'` `'voided'` | +| `QuoteStatus` | `'draft'` `'sent'` `'accepted'` `'declined'` `'voided'` | | `BillingFrequency` | `'monthly'` `'quarterly'` `'annual'` `'one-time'` | | `Currency` | `'USD'` `'EUR'` `'GBP'` `'CAD'` `'AUD'` `'INR'` | | `RenewalPeriod` | `'weekly'` `'monthly'` `'quarterly'` `'annually'` | @@ -5742,6 +6297,26 @@ try { +#### TurboQuote error codes {#turboquote-error-codes} + +Every typed error carries the API's `code` (`err.code`, `e.code`, `$e->errorCode`, `err.Code`, `e.getCode()`). The codes you're most likely to branch on: + +| Status | Code | When | +|---|---|---| +| 409 | `CANNOT_DELETE_SENT_QUOTE` | Deleting a sent quote. Void it instead. | +| 409 | `CANNOT_DELETE_ACCEPTED_QUOTE` | Deleting an accepted quote. It's kept for your records. | +| 409 | `CompanyHasOpenQuotes` | Deleting a company that has open quotes (draft or sent). See `getCompanyOpenQuotes`. | +| 409 | `ContactHasOpenQuotes` | Deleting a contact who is on open quotes. See `getContactOpenQuotes`. | +| 409 | `LastContact` | Deleting a company's only contact. | +| 400 | `PriceBookIsDefault` | Deleting the organization's default price book. | +| 400 | `MAX_IMAGES_EXCEEDED` | More than three images on a product or custom line item. | +| 400 | `IMAGE_TOO_LARGE` / `INVALID_FILE_TYPE` | An image over 2 MB, or not PNG / JPEG. | +| 400 | `QUOTE_NOT_EDITABLE` | Changing a quote (or its line items or images) that isn't a draft. | +| 404 | `QUOTE_NOT_FOUND`, `LINE_ITEM_NOT_FOUND`, `IMAGE_NOT_FOUND` | The quote, line item or image doesn't exist in your organization. | +| 400 | `SenderEmailRequired` | An API-key caller whose quote template has no sender email. | + +Money fields are capped at 9,999,999,999,999.99, quantities at 2,147,483,647 and percents at 999.99 (a percent discount at 100); a larger value is a 400 with the field named. An amount discount larger than the price it comes off is a 400. + ## Runnable Examples / Runnable End-to-End Examples {#runnable-examples} diff --git a/docs/TurboQuote/Adding-a-New-Product.md b/docs/TurboQuote/Adding-a-New-Product.md index 07ccc9b8..5fdbf72f 100644 --- a/docs/TurboQuote/Adding-a-New-Product.md +++ b/docs/TurboQuote/Adding-a-New-Product.md @@ -1,200 +1,133 @@ --- title: Adding a New Product -sidebar_position: 2 -description: Learn how to add a new custom product to a sales quote in TurboQuote, including setting up product details, category, billing frequency, and pricing. +sidebar_position: 3 +description: Add products to your TurboQuote catalog with category, billing, list price, cost and up to three images, then hide, duplicate or delete them from the Products page. keywords: - turboquote - add product - new product - product catalog - - quote line item + - product images - pricing - billing frequency + - duplicate product - TurboDocx --- -# Adding a New Product to a Quote +# Adding a New Product -This guide walks you through adding a new custom product to a sales quote in TurboQuote. You'll learn how to create a product record with category, billing frequency, and pricing details, then insert it as a line item in your quote. +Products are the things you sell, each with a list price and how often it is billed. Reps add them to quotes from the catalog, so a product you set up once can be reused on every quote. ## What You'll Accomplish By the end of this guide, you will have: -- 🗂️ **Opened the product catalog** from within a quote -- 📦 **Created a new product** with name, category, and billing frequency -- 💵 **Set up list price** and optional cost for margin tracking -- ➕ **Inserted the product** as a line item in your active quote +- 📦 **Created a product** with a name, SKU, category and billing +- 💵 **Set its list price** and cost, and checked the margin +- 🖼️ **Added product images** that appear on quotes +- 🗂️ **Managed your catalog**: hidden, duplicated and deleted products :::tip Quick Start Promise -Adding products to your catalog takes only a moment, and reusable products make every future quote faster to build. 🚀 +A product takes about a minute to add. Have a lot of them? [Import them from a spreadsheet](./Bulk-Importing-from-a-Spreadsheet.md) instead. 🚀 :::
-## Step 1: Open the Add Product Interface - -Initiate the process of adding a product line item to the current quote by accessing the product selection interface. This sets the stage for searching, selecting, or creating products to enrich the quote. - -**Instruction:** - -- Click the **+ Add Product** button in the top action bar above the quote line items section. - -![Open the Add Product interface](/img/turboquote/product-step-01.png) - -
- -## Step 2: Begin Creating a New Product - -Open the new product creation form when the desired product is not available in the existing catalog. This step enables adding a new product record to reuse in the quote and future transactions. - -**Instruction:** - -- In the Product Catalog dialog, click the **+ New Product** button located to the right of the search field. - -![Begin creating a new product](/img/turboquote/product-step-02.png) - -
- -## Step 3: Focus the Product Name Field - -Set the cursor in the Product Name input field to begin specifying a clear and recognizable name for the new product. +## Step 1: Open the Products Page **Instruction:** -- Click on the **Product Name** text input field near the top of the New Product form. - -![Focus the Product Name field](/img/turboquote/product-step-03.png) - -
- -## Step 4: Select or Enter a Product Category +- In the sidebar, open **TurboQuote** and click **Products**, then click **New product**. -Identify or create a category for the new product to organize it properly within the catalog for easier selection and reporting. - -**Instruction:** +You can also create a product while building a quote: click **Add products**, then **New product** in the dialog. -- Click on the **Category** text field in the New Product form to begin searching or entering a category. - -![Select or enter a product category](/img/turboquote/product-step-04.png) +![The Products page with the New product button](/img/turboquote/products/01-products.png)
-## Step 5: Choose a Category from the Dropdown - -Assign the new product to a category to align it with similar catalog items and facilitate proper organization. +## Step 2: Fill In the General Tab **Instruction:** -- Click the desired category option (e.g. **Hardware (Default)**) from the Category dropdown list. +1. Enter the **Name**. Customers see it on quotes. +2. Optionally enter a **SKU**, your own code for the product. Bundles and price books use it when you import them from a spreadsheet. +3. Pick a **Category**, or type a new name to create one. Quotes list items under their category. +4. Choose the **Billing**: **One-time**, **Monthly**, **Quarterly** or **Yearly**. +5. Set the **Minimum order**. Quotes start at this quantity. +6. Optionally add a **Description**, shown under the name on quotes and in lists, and **Internal notes**, which only your team sees. +7. Leave **Show in the catalog** on so reps can add the product to quotes. -![Choose a category](/img/turboquote/product-step-05.png) +![The General tab of a new product](/img/turboquote/products/03-new-product-general.png)
-## Step 6: Open the Billing Frequency Dropdown - -Review or change the billing frequency to ensure it matches the intended sales and revenue model for the new product. +## Step 3: Set the Price **Instruction:** -- Click on the **Billing Frequency** dropdown field currently showing **Monthly Recurring**. +1. Open the **Pricing** tab. +2. Choose the **Currency**. The price and cost are in this currency, and the product can only be added to quotes in the same currency. +3. Enter the **List price**, the price before any discount or price book. Use 0 for a free product. +4. Optionally enter **Your cost**. It is only used to work out the margin. -![Open the Billing Frequency dropdown](/img/turboquote/product-step-06.png) +The **Margin** panel shows the margin and the profit per unit as you type. -
+![The Pricing tab with list price, cost and a 39% margin](/img/turboquote/products/04-new-product-pricing.png) -## Step 7: Select a Billing Frequency - -Switch the billing schedule to correspond with the product's sales type. - -**Instruction:** - -- Click on the desired option (e.g. **One-Time**) in the Billing Frequency dropdown list. - -![Select billing frequency](/img/turboquote/product-step-07.png) - -
- -## Step 8: Navigate to the Pricing & Costs Tab - -Access the section to configure pricing details of the new product after setting general information. - -**Instruction:** - -- Click on the **Pricing & Costs** tab in the New Product dialog's tab bar. - -![Navigate to Pricing & Costs tab](/img/turboquote/product-step-08.png) - -
- -## Step 9: Enter the List Price - -Focus on the List Price field to input or modify the product's list price amount for quoting. - -**Instruction:** - -- Click inside the **List Price** text input field in the Pricing & Costs tab. - -![Enter the list price](/img/turboquote/product-step-09.png) +:::note Changing a price later +When you lower a product's price, TurboQuote updates the price books and bundles that use it. A price book or bundle that took more off than the new price is capped at the new price. +:::
-## Step 10: Enter the Optional Cost Value - -Specify the internal cost of the product to enable accurate margin tracking, if applicable. +## Step 4: Add Images (Optional) **Instruction:** -- Click on the **Cost (Optional)** input field in the Pricing & Costs tab. - -![Enter the optional cost value](/img/turboquote/product-step-10.png) - -
+1. Open the **Images** tab. +2. Drop images on the upload area, or click it to choose files. A product can have up to **3 images**, JPEG or PNG, up to 2 MB each. +3. Drag an image by its grip (or use the arrow keys on it) to change the order. Quotes show the images side by side in this order. -## Step 11: Submit the New Product +The **On a quote** preview shows how the images will look on a line item. -Finalize and save the new product record to update the product catalog and make it available to add to the quote. +![The Images tab with one image and the On a quote preview](/img/turboquote/products/05-new-product-images.png) **Instruction:** -- Click the blue **Create Product** button at the bottom-right of the New Product dialog. - -![Submit the new product](/img/turboquote/product-step-11.png) +- Click **Create product**.
-## Step 12: Open Additional Options for the Product +## Managing Your Catalog -Access extra settings or detailed information about the new product within the catalog. +### Show or hide a product -**Instruction:** +The **In catalog** switch on each row controls whether reps can add the product to new quotes. A hidden product stays in your catalog and on the quotes that already use it. The **All**, **In catalog** and **Hidden** tabs filter the list. -- Click on the circular icon button in the top-right corner of the product card. +![The All, In catalog and Hidden tabs, and the In catalog switch on a product](/img/turboquote/products/02-catalog-tabs.png) -![Open additional options](/img/turboquote/product-step-12.png) +### Edit, duplicate or delete a product -
+Click the **⋮** button on a product to **Edit**, **Duplicate** or **Delete** it. -## Step 13: Insert the Product into the Quote - -Complete the process by adding the created product as a line item in the active quote. - -**Instruction:** +![The product menu with Edit, Duplicate and Delete](/img/turboquote/products/06-product-actions.png) -- Click the blue **+ Insert 1 Product** button at the bottom-right of the Product Catalog dialog. +**Duplicate** asks for the **Name of the copy**, which starts as **Copy of …**. The copy keeps the price, cost, billing, category, description, notes and images, and its SKU gets a **-COPY** suffix. -![Insert the product into the quote](/img/turboquote/product-step-13.png) +![The Duplicate dialog with the name of the copy](/img/turboquote/products/07-duplicate.png)
## Summary -You've successfully added a new custom product to your quote in TurboQuote! Here's a recap of what you accomplished: +1. Create products from the **Products** page or from **Add products** in a quote +2. Set the **category**, **billing**, **list price** and optional **cost** +3. Add up to **3 images** that appear on quotes +4. Use the **In catalog** switch to hide a product without deleting it -1. Opened the product catalog from the quote interface -2. Created a new product with a name and category -3. Configured billing frequency and pricing details -4. Inserted the product as a line item in your active quote +## Related -Your product is now saved in the catalog for future use and has been added to the current quote. You can continue adding more products or proceed to finalize your quote. +- [Managing Bundles](./Managing-Bundles.md) +- [Managing Price Books](./Managing-Price-Books.md) +- [Bulk Importing from a Spreadsheet](./Bulk-Importing-from-a-Spreadsheet.md) +- [Managing Categories](./Managing-Categories.md) diff --git a/docs/TurboQuote/Bulk-Importing-from-a-Spreadsheet.md b/docs/TurboQuote/Bulk-Importing-from-a-Spreadsheet.md index cde1ad7e..ee5ca257 100644 --- a/docs/TurboQuote/Bulk-Importing-from-a-Spreadsheet.md +++ b/docs/TurboQuote/Bulk-Importing-from-a-Spreadsheet.md @@ -1,7 +1,7 @@ --- title: Bulk Importing from a Spreadsheet -sidebar_position: 3 -description: Bulk import products, companies, contacts, and bundles into TurboQuote from CSV or XLSX with column mapping, validation, and error reports. +sidebar_position: 8 +description: Bulk import products, companies, contacts, bundles, price books and categories into TurboQuote from CSV or Excel, with column matching, validation and error reports. keywords: - turboquote - bulk import @@ -18,14 +18,14 @@ keywords: # Bulk Importing from a Spreadsheet -Instead of creating catalog and CRM records one at a time, you can import them in bulk from a CSV or XLSX spreadsheet. This is the fastest way to load an existing catalog exported from your CRM, ERP, or a previous tool. +Instead of creating catalog and CRM records one at a time, you can import them in bulk from a CSV or Excel spreadsheet. This is the fastest way to load an existing catalog exported from your CRM, ERP, or a previous tool. ## What You'll Accomplish By the end of this guide, you will have: -- 📤 **Uploaded** a CSV or XLSX file to a TurboQuote import dialog -- 🔗 **Mapped** your spreadsheet columns to TurboQuote fields +- 📤 **Uploaded** a CSV or Excel file to a TurboQuote import dialog +- 🔗 **Matched** your spreadsheet columns to TurboQuote fields - ✅ **Reviewed** validation results and imported your records - 📥 **Downloaded an error report** for any rows that need fixing @@ -44,90 +44,80 @@ Related records connect using the names and codes you already use, so you can bu ## What You Can Import -Bulk import is available for each of these record types, from its own list page: +Bulk import is available for each of these record types. On each page, click the **Import** button next to the **New …** button: -| Record type | Where to find it | Button | -| --- | --- | --- | -| **Products** | TurboQuote → Products | **Import from Spreadsheet** | -| **Companies** (with their contacts) | TurboQuote → Companies | **Import from Spreadsheet** | -| **Contacts** | A company's Contacts page | **Import from Spreadsheet** | -| **Bundles** | TurboQuote → Bundles | **Import from Spreadsheet** | -| **Price Books** | TurboQuote → Price Books | **Bulk Create** | -| **Categories** | TurboQuote → Categories | **Bulk Create** | +| Record type | Where to find it | +| --- | --- | +| **Products** | TurboQuote → Products | +| **Companies** (with their contacts) | TurboQuote → Companies | +| **Contacts** | A company's Contacts page | +| **Bundles** | TurboQuote → Bundles | +| **Price Books** | TurboQuote → Price Books | +| **Categories** | TurboQuote → Manage Categories, on the tab for the kind of category | -The button to open the importer sits next to **New …** on each page. - -![The Products page with the Import From Spreadsheet button highlighted in the top-right toolbar](/img/turboquote_bulk_import/01_products_import_button.png) +![The Products page with the Import button highlighted](/img/turboquote_bulk_import/00-import-button.png) ## Step 1: Upload Your File -This walkthrough uses **Products** as the example. Companies, contacts, bundles, price books, and categories follow the same three steps; only the column names differ (see the [Column Reference](#column-reference)). For price books and categories, the button is labeled **Bulk Create** instead of **Import from Spreadsheet**. - -1. Click **Import from Spreadsheet** (or **Bulk Create**, for price books and categories) to open the import dialog. -2. (Recommended) Click **Download template** in the top-right of the **Columns** box to get a correctly formatted CSV with the right column headers and an example row. -3. Drag and drop your **CSV** or **XLSX** file onto the upload area, or click to browse. +This walkthrough uses **Companies** as the example, because a company can span several rows (one per contact). Products, contacts, bundles, price books and categories follow the same three steps; only the columns differ (see the [Column Reference](#column-reference)). -The dialog parses your file and shows the row and column counts plus a preview. +1. Click **Import** to open the import dialog. +2. Check **What the file needs**. It lists the **required** and **optional** columns. For companies there are two groups: the company's own columns, and the columns for each contact. +3. (Recommended) Click **Download template** to get a CSV with the right column headers and an example row. +4. Drag and drop your **CSV** or **Excel** file onto the upload area, or click it to choose one. +5. Click **Continue**. -- 📦 **Maximum 500 rows** per import. A larger file is rejected before anything is created, with a message like _"Spreadsheet contains 750 rows, which exceeds the maximum of 500. Please reduce the number of rows."_ Split the file into batches and import each one. +- 📦 **Maximum 500 rows** per import. A larger file is rejected before anything is created. Split the file into batches and import each one. - 📅 Date columns (for example, a price book's valid-from and valid-to) are read in `YYYY-MM-DD` format. -![The Upload step with the drag-and-drop upload area highlighted; above it, the Columns box lists the required and optional fields and the Download Template button](/img/turboquote_bulk_import/02_upload_step.png) +![The Upload file step. What the file needs lists the required and optional columns for companies and for each contact](/img/turboquote_bulk_import/01-upload.png) + +For products, **What the file needs** also explains the billing values and that new categories are created for you: + +![The products import: Name, Billing Frequency, List Price and Category are required](/img/turboquote_bulk_import/05-products-upload.png) -## Step 2: Map Your Columns +## Step 2: Match Your Columns -TurboQuote auto-detects common column names (for example, `product_name` maps to **Product Name**). Header matching ignores case, spaces, and underscores, so `Product Name`, `product_name`, and `PRODUCTNAME` are all recognized. On the **Map Columns** step you can confirm or change each mapping: +TurboQuote matches your columns by name. Matching ignores case, spaces and underscores, so `Company Name`, `company_name` and `COMPANYNAME` are all recognised, and a few common alternates work too (for example, `Company` for the company name). On the **Match columns** step, each field shows the column it was matched to and a status: -- **Required fields** are marked with an asterisk and must be mapped before you can continue. -- **Optional fields** can be left unmapped. Sensible defaults are applied (for example, currency defaults to USD). +- **Matched**: the field will be filled from that column. +- **Skipped**: no column was matched, or you chose **Don't import**. Only optional fields can be skipped. -If you used the downloaded template, every column maps automatically. +Change any match with the dropdown next to the field. Required fields are marked with an asterisk and must be matched before you can continue. If you used the downloaded template, every column matches automatically. -![The Map Columns step with the Required Fields group highlighted, each required field auto-mapped to a spreadsheet column](/img/turboquote_bulk_import/03_map_columns.png) +![The Match columns step for the company fields, each matched to a column of the file](/img/turboquote_bulk_import/02-match-columns.png) + +For companies, the **Contact Fields** come next. Rows with the same company name are grouped into one company, and each row adds one contact. + +![The Contact Fields: Contact Name and Contact Email are required, and Contact Phone is skipped](/img/turboquote_bulk_import/03-contact-columns.png) ## Step 3: Review and Import -The **Review & Import** step checks every row **before anything is created**, then sorts your rows into three groups, shown as a colored bar and a summary headline (for example, **"4 of 5 rows will import"**): +The **Review & import** step checks every row **before anything is created**, then sorts your rows into three groups, shown as a colored bar and a summary headline (for example, **"1 of 2 rows will import"**): - ✅ **Import as-is.** The row is clean and imports unchanged. - ⚠️ **Import with changes.** The row still imports, but a bad **optional** value was cleared. For example, a non-numeric `cost`, an unrecognized `currency`, or an out-of-range minimum order quantity is dropped and the rest of the row is kept (currency falls back to the default, USD). -- ❌ **Won't import.** A **required** value is missing or invalid, so the whole row is skipped. For example, a product with no name or an invalid billing frequency, or a bundle row missing its unit price. +- ❌ **Won't import.** A **required** value is missing or invalid, so the whole row is skipped. For example, a product with no name, or a company whose industry doesn't match an existing industry. Expand any group to see the affected rows with their row number and the exact reason. -When you're happy with the split, click **Import _N_ rows**. The button shows how many will import. TurboQuote creates any missing categories or price-book types first, then imports the eligible rows. +For companies, rows are grouped by company before counting, so the headline counts **companies**, not spreadsheet rows. In this example, three rows (two contacts for Alpine Ski House, one for Woodgrove Bank) are **two companies**, and one of them won't import because its industry doesn't exist yet. -![The Review and Import step showing the three colored groups (import as-is, import with changes, won't import) and the Import 4 Rows button highlighted](/img/turboquote_bulk_import/04_review_import.png) +![The Review & import step: 1 of 2 rows will import. Row 4, Woodgrove Bank, won't import because its industry doesn't match an existing industry](/img/turboquote_bulk_import/04-review.png) -:::tip Importing companies with contacts? -A company can span several rows, one per contact, so it works a little differently. See the [worked example](#example-importing-companies-and-contacts) below. -::: +When you're happy with the split, click **Import _N_** (for example, **Import 1 company**). The button shows how many will import. TurboQuote creates any missing categories first, then imports the eligible rows. ### Adjustments and Error Reports -After importing, the headline updates to something like **"4 of 5 rows imported"**, keeping the same three groups. Two downloads help you follow up: +After importing, the headline updates to something like **"1 of 2 rows imported"**, keeping the same groups. Two downloads help you follow up: - **Download changes.** A report of every row that imported **with changes** (which value was cleared, and why), so you can fill them back in later. -- **Download errors.** A report of every row that **didn't import**. Fix those rows in your spreadsheet and re-upload just them. +- **Download errors.** A report of every row that **didn't import**. Fix those rows in your spreadsheet and upload just them again. :::tip Why your file rarely fails outright A bad **optional** value never blocks a row. TurboQuote clears just that value and keeps the rest. Only a missing or invalid **required** value skips a row. So even a messy export gets most of your data in, and the change and error reports tell you exactly what to clean up. ::: -## Example: Importing Companies and Contacts - -The companies importer works the same way as the products importer, but with one key difference: a company can span **several rows**, one per contact. You open it from **TurboQuote → Companies** with the **Import From Spreadsheet** button. - -![The Companies page with the Import From Spreadsheet button highlighted in the top-right toolbar](/img/turboquote_bulk_import/05_companies_import_button.png) - -On the **Map Columns** step, the fields are split into two groups: **Company Fields** (the company-level columns like name, phone, and city) and **Contact Fields** (the per-contact columns like contact name and email). Rows that share the same company name are grouped into one company, and each row adds one contact. - -![The Companies Map Columns step with the Company Fields and Contact Fields groups highlighted](/img/turboquote_bulk_import/06_companies_map.png) - -The **Review & Import** step groups the rows by company before counting, so the headline counts **companies**, not spreadsheet rows. In this example, three spreadsheet rows (two contacts for one company, one for another) become **two companies** — the review reads **"2 of 2 rows will import"** (one per company), and the **Import 2 Companies** button confirms the count before anything is created. - -![The Companies Review and Import step showing 2 of 2 rows will import and the Import 2 Companies button highlighted](/img/turboquote_bulk_import/07_companies_review.png) - ## Column Reference You only need this section if you're building a spreadsheet by hand. If you started from **Download template**, your headers already match and every column maps automatically, so you can skip ahead to [Tips and Limits](#tips-and-limits). @@ -188,13 +178,13 @@ Price-book-level columns (repeat the same values on every row of the price book) | Column | Required? | Example | Notes | | --- | --- | --- | --- | | `price_book_name` | **Required** | Q1 Enterprise | Also accepts `price_book`, `name`. Groups the rows of one price book. | -| `type` | **Required** | Enterprise | Price book type. Created automatically if it does not exist. | +| `category` | **Required** | Enterprise | Price book category. Also accepts `type`. Created automatically if it does not exist. | | `valid_from` | **Required** | 2026-01-01 | `YYYY-MM-DD`. | | `description` | Optional | First quarter rates | | | `discount_percent` | Optional | 10 | 0 to 100. Defaults to 0. | | `valid_to` | Optional | 2026-12-31 | `YYYY-MM-DD`. Must be after `valid_from`. | | `is_default` | Optional | false | Defaults to false. | -| `show_in_quote_builder` | Optional | true | Defaults to true. | +| `offer_on_quotes` | Optional | true | Whether reps can pick the book on quotes. Also accepts `show_in_quote_builder`. Defaults to true. | Per-product override columns (one row per product): @@ -211,7 +201,7 @@ Per-product override columns (one row per product): | --- | --- | --- | --- | | `category_name` | **Required** | Software Licenses | Also accepts `name`, `category`. | -The category **type** (Product, Bundle, Price Book, or Industry) comes from which **Bulk Create** button you click on the Categories page, not from a column. Open the importer under the heading you want, and every row is created as that type. +The kind of category (product, bundle, price book or industry) comes from the tab you are on when you click **Import** on the Categories page, not from a column. Open the tab you want first, and every row is created as that kind. ### Companies (TurboQuote → Companies) @@ -220,11 +210,12 @@ Company-level columns (repeat the same values on every row of the company): | Column | Required? | Example | Notes | | --- | --- | --- | --- | | `company_name` | **Required** | Acme Corp | Also accepts `company`, `name`. Groups the rows of one company. | +| `company_email` | **Required** | hello@acme.com | The company's own email address. | +| `industry` | **Required** | Technology | Must be an existing industry name. See the note below. Also accepts `sector`, `vertical`. | | `phone` | Optional | +1 555-123-4567 | | | `city` | Optional | New York | | | `state` | Optional | NY | Also accepts `province`. | | `country` | Optional | United States | | -| `industry` | Optional | Technology | Must be an existing industry name. See the note below. | Per-contact columns (one row per contact; each company needs at least one): @@ -258,7 +249,7 @@ Some records span **multiple rows** in your spreadsheet: For these, all rows that share the same record name must repeat the same record-level values (company industry, bundle discount, price book type, and so on). **Only the per-item columns may differ between rows.** If two rows disagree on a record-level value, the import flags a conflict so nothing is created with the wrong value. :::note Categories and types are created for you -When you import products, bundles, or price books, any category or price-book type that doesn't exist yet is created automatically before the records are imported. Company **industries** are the exception: they must already exist, so use a recognized industry name. You can pre-create industries in bulk from the **Industry Categories** section of the Categories page. +When you import products, bundles, or price books, any category or price-book type that doesn't exist yet is created automatically before the records are imported. Company **industries** are the exception: they must already exist, so use a recognized industry name. You can add industries, one at a time or in bulk, on the **Industries** tab of the Categories page. ::: ## Referencing Products by SKU (Bundles and Price Books) @@ -285,4 +276,7 @@ Import your **products first**, then reference them by SKU in your bundle and pr ## Related - [Adding a New Product](./Adding-a-New-Product.md) -- [Creating a New Quote](./Creating-a-New-Quote.md) +- [Managing Companies and Contacts](./Managing-Companies-and-Contacts.md) +- [Managing Bundles](./Managing-Bundles.md) +- [Managing Price Books](./Managing-Price-Books.md) +- [Managing Categories](./Managing-Categories.md) diff --git a/docs/TurboQuote/Creating-a-New-Quote.md b/docs/TurboQuote/Creating-a-New-Quote.md index 9c98b0d1..4786dafa 100644 --- a/docs/TurboQuote/Creating-a-New-Quote.md +++ b/docs/TurboQuote/Creating-a-New-Quote.md @@ -1,204 +1,263 @@ --- title: Creating a New Quote sidebar_position: 1 -description: Learn how to create a new professional quote in TurboQuote, including setting up company and contact details. +description: Create a quote in TurboQuote from start to send. Pick the customer, set the quote details, add products, bundles and custom items, then preview and send it for signature. keywords: - turboquote - quote creation - create quote - new quote - - company details - - contact details + - custom line item + - send quote + - quote builder - professional quote - TurboDocx --- # Creating a New Quote -This guide walks you through the complete process of creating a new professional quote using TurboQuote. You'll learn how to initiate a quote, set up a company with contact information, and finalize the quote for your client. +This guide walks you through a quote from start to finish: choosing who it is for, setting its details, adding what you are selling, and sending it for signature. ## What You'll Accomplish By the end of this guide, you will have: -- 🧾 **Created a new quote** from the TurboDocx home screen -- 🏢 **Added a new company record** with industry classification -- 👤 **Set up contact details** for the company -- ✅ **Named and submitted** your completed quote +- 👤 **Picked the contact** who receives and signs the quote +- 🧾 **Set the quote details**: name, number, currency, quote type, term, valid-until date and tax +- 📦 **Added products, bundles and a custom item**, with quantities and discounts +- 👀 **Previewed** the quote as your customer will see it +- ✉️ **Sent it** with reminders, ready for signature +- ✅ **Know what happens next**, from Sent to Accepted :::tip Quick Start Promise -Creating your first quote takes just a few minutes. Follow along and you'll have a professional, ready-to-send quote in no time! 🚀 +A quote takes a few minutes, and everything saves as you go. You can stop at any point and pick it up again from the Quotes page. 🚀 :::
-## Step 1: Start Creating a New Quote from the Main TurboDocx Home Screen - -Begin the process of creating and sending a new professional quote using TurboQuote. The main options section provides the entry point to initiate this workflow, setting up the workspace to add client details, products, and pricing. +## Step 1: Start a New Quote **Instruction:** -- Click on the **Create a Quote** card in the main options section to start building a new quote. +- On the **Quotes** page, click **New quote** in the top-right corner. + +You can also start a quote from the **Create a Quote** card on the TurboDocx home screen. -![Start creating a new quote from the home screen](/img/turboquote/step-01.png) +![The New quote button on the Quotes page](/img/turboquote/new-quote/01-new-quote-button.png)
-## Step 2: Initiate Quote Creation from the TurboQuote Quotes List Page +## Step 2: Pick Who the Quote Is For -Access the TurboQuote module directly to begin creating a new quote. This will transition to the quote creation interface where detailed quote information can be provided. +The **Who is this quote for?** page lists your contacts, with your **Recent customers** first. Search by name, email or company, or switch to the table view if you prefer a list. **Instruction:** -- Click the **+ New Quote** button located in the top-right toolbar of the quotes page. +- Click the contact who will receive and sign the quote. + +![The contact picker with Recent customers and All contacts. The contact Liam Patel is selected](/img/turboquote/new-quote/02-pick-contact.png) + +### Quoting someone new? + +If the customer isn't in TurboQuote yet, click **Add new** and choose **New company** or **New contact**. A new company needs at least one contact, so you can add both in one go. The new contact is then picked for the quote. See [Managing Companies and Contacts](./Managing-Companies-and-Contacts.md) for the fields. -![Initiate quote creation from the quotes list](/img/turboquote/step-02.png) +![The Add new menu with New company and New contact](/img/turboquote/new-quote/03-add-new.png)
-## Step 3: Open the Add New Menu on the Quote Creation Page +## Step 3: Fill In the Quote Details -Access options to add new contacts or related items while building the quote. This menu exposes additional creation flows necessary for completing the quote setup. +The **Quote details** dialog opens for the contact you picked. **Instruction:** -- Click the purple **Add New** button on the quote page to reveal more creation options. +1. Type a **Quote name**. Your customer sees it on the quote and on the signature request. +2. Check the **Currency**. Only products and bundles in this currency can be added, and it can't be changed once the quote is created. +3. Choose the **Quote type**: + - **One-time**: hardware, projects or services, with no contract. + - **Fixed term**: recurring services for a set period. Enter the **Contract length** in months or years (up to 10 years). + - **Auto-renewing**: renews until the customer cancels. +4. Check **Valid until**. It defaults to 30 days from today; the customer can sign until then. +5. Turn on **Tax** if you charge it, and enter the rate (0 to 100, two decimals). It is applied to the subtotal. -![Open the Add New menu](/img/turboquote/step-03.png) +![The Quote details dialog with the quote name filled in](/img/turboquote/new-quote/04-quote-details.png) -
+![The three quote types: One-time, Fixed term and Auto-renewing](/img/turboquote/new-quote/05-quote-type.png) + +### The quote number -## Step 4: Select New Company from the Add New Dropdown +The **Quote number** shows the number this quote will get. It is assigned when you create the quote. To change the format, click **Edit numbering**: the **Quote numbering** dialog is the same as **Settings › Quote numbering** and shows the next numbers as you edit. Changes apply to quotes created from then on. See [How to Configure Quote Numbering](./How-to-Configure-Quote-Numbering.md). -Create a new company record to associate with the quote. This ensures the quote is linked to an up-to-date company profile for accurate tracking and communication. +![The Quote numbering dialog with a preview of the next quote number](/img/turboquote/new-quote/06-numbering.png) **Instruction:** -- Click the **New Company** option in the dropdown menu under the **Add New** button. +- Click **Create quote**. -![Select New Company from dropdown](/img/turboquote/step-04.png) +![The Create quote button](/img/turboquote/new-quote/07-create-quote.png)
-## Step 5: Focus the Company Name Field in the Create Company Form - -Begin entering the company's name, which is the primary identifier for the new company record. - -**Instruction:** +## Step 4: Add What You're Selling -- Click on the **Company Name** text input field at the top of the Create Company form to activate text entry. +The quote opens in the builder. The header shows the customer, valid-until date, term, tax and price book; the **Quote total** on the right updates with every change. There is no Save button: changes save automatically. -![Focus the Company Name field](/img/turboquote/step-05.png) +The **Line items** section has three ways to add items: -
+- **Add products**: from your product catalog. +- **Add bundles**: products sold together at one price. +- **Custom item**: a one-off item for this quote only. -## Step 6: Open Industry Selection Options in Create Company Form +![The empty quote builder with the Add products, Add bundles and Custom item buttons](/img/turboquote/new-quote/08-builder-empty.png) -Access the interface to select an industry or create a new one, specifying the business category associated with the company. +### Add products **Instruction:** -- Click the icon button at the right side of the **Select or create industry...** field within the Create Company form. +1. Click **Add products**. +2. Tick the products you want. You can set each one's quantity right in the list. +3. Click **Add N products**. -![Open industry selection options](/img/turboquote/step-06.png) +Prices come from the quote's **price book**, shown at the top of the dialog. The footer shows what you have selected and its total. If a product is missing, click **New product** to create it without leaving the quote. -
+![The Add products dialog with three products ticked and a quantity of 40 on Wireless Access Point](/img/turboquote/new-quote/09-add-products.png) -## Step 7: Choose an Industry from the Dropdown +### Adjust quantities and discounts -Define the company's industry by selecting the appropriate preset industry from the dropdown list. +Each line has a quantity, a unit price and a **discount per unit**. Choose **%** for a percentage or **$** for an amount off each unit. Items are grouped under their category, and you can drag a line or a whole category to reorder them. -**Instruction:** +![A line item with a quantity of 40 and a 10% discount per unit](/img/turboquote/new-quote/10-line-items.png) -- Click on the desired industry option (e.g. **Construction (Default)**) in the Industry dropdown list to select it for the company. +The **Quote total** shows the total, how much of it recurs and for how long, and a line for each billing type. **Overall margin** shows your profit on the quote, worked out from the cost of each product. It is for you only and never appears on the quote. -![Choose industry from dropdown](/img/turboquote/step-07.png) +![The Quote total with one-time and yearly lines, and the overall margin](/img/turboquote/new-quote/11-quote-total.png) -
+### Change the price book -## Step 8: Edit the Contact Name Field in the Create Company Form - -Focus on the primary contact's name field to enter or modify the contact person's full name. +Every new quote starts with your organization's **default** price book, shown under **Price book** in the header. To price this quote with a different book, for example partner or nonprofit pricing: **Instruction:** -- Click on the **Name** text input field under the **Contact 1** section in the Create Company form to activate the text cursor. +1. Click **Price book** in the header. +2. Pick the book you want. Each book shows its discount and the dates it is valid. Only books that are offered on quotes appear. +3. Click **Apply price book**. + +![The Price book in the quote header, showing Standard Pricing](/img/turboquote/new-quote/11a-price-book-button.png) -![Focus the contact name field](/img/turboquote/step-08a.png) +![The Price book dialog with Nonprofit Program picked and the Apply price book button](/img/turboquote/new-quote/11b-price-book-dialog.png) -![Enter the contact name](/img/turboquote/step-08b.png) +Every catalog product on the quote is repriced from the new book, and any discount you set on those lines is reset. Bundles and custom items keep their prices. If a book changes after you applied it, the dialog says so; click **Apply again** to pick up the new prices. To stop using a price book, click **Remove price book**: the quote keeps its current prices. + +See [Managing Price Books](./Managing-Price-Books.md) to set up the books themselves.
-## Step 9: Enter the Contact Email Address +## Step 5: Add a Custom Item (Optional) -Prepare to enter or update the email address for the primary contact, which is essential for communication related to the quote. +Use a custom item for something you sell once, such as a site survey. It lives on this quote only and is not added to your catalog. **Instruction:** -- Click on the email address text input field under **Contact 1** in the Create Company form to focus it for editing. +1. Click **Custom item**. +2. On the **General** tab, enter the **Name**, an optional **SKU**, the **Category** and the **Billing**, and an optional **Description**. +3. On the **Pricing** tab, enter the **Unit price** and, optionally, **Your cost** to see the margin. A custom item always uses the quote's currency. +4. On the **Images** tab, add up to **3 images** (JPEG or PNG, up to 2 MB each). Drag them by their grip to change the order; the quote shows them side by side in that order. +5. Click **Add to quote**. -![Enter the contact email address](/img/turboquote/step-09.png) +![The General tab of a new custom item](/img/turboquote/new-quote/12-custom-item.png) -
+![The Pricing tab with the unit price, your cost and the margin](/img/turboquote/new-quote/13-custom-item-pricing.png) -## Step 10: Submit the Create Company Form +![The Images tab with one image and a preview of how it looks on a quote](/img/turboquote/new-quote/14-custom-item-images.png) -Complete the creation of the new company record along with its associated contact details by submitting the form. +The item is added at quantity 1 with no discount, and carries a **Custom** tag. Set its quantity and discount in the table like any other line. To change its name, price or images later, click its **⋮** button and choose **Edit**. + +![The custom item in the line items, tagged Custom](/img/turboquote/new-quote/15-custom-item-row.png) + +![The custom item's menu with Edit and Remove](/img/turboquote/new-quote/16-custom-item-menu.png) + +
+ +## Step 6: Add Bundles (Optional) **Instruction:** -- Click the **Create Company** button located at the bottom-right of the modal to submit the form. +1. Click **Add bundles**. +2. Tick the bundles you want and set their quantity. +3. Click **Add N bundles**. -![Submit the Create Company form](/img/turboquote/step-10.png) +Each bundle shows its price for each billing type, so you can see what the customer pays once and what recurs. + +![The Add bundles dialog with Remote Team Kit ticked](/img/turboquote/new-quote/17-add-bundles.png)
-## Step 11: Select the Contact Card for the New Quote +## Step 7: Change the Details Later (Optional) + +Click **Edit details** in the header to change the quote type, contract length, **Valid until** or **tax**. To rename the quote, click its name at the top of the page. The currency is fixed once a quote is created. + +![The Edit quote details dialog with the Tax switch](/img/turboquote/new-quote/18-edit-details.png) + +
-Associate the newly created contact with the quote by selecting their contact card. +## Step 8: Preview the Quote **Instruction:** -- Click on the contact card labeled with the contact's name to select this contact for the quote. +- Click **Preview & send** in the top-right corner. -![Select the contact card](/img/turboquote/step-11.png) +![The Preview & send button](/img/turboquote/new-quote/19-preview-send-button.png) -
+The preview shows the quote exactly as your customer will see it, including images on custom items. From the bar at the bottom you can go back with **Edit quote**, **Download PDF**, or **Send quote**. -## Step 12: Submit the Completed Quote +![The quote preview with Download PDF and Send quote](/img/turboquote/new-quote/20-preview.png) -Finalize and create the new quote record by submitting the detailed quote information after linking company and contact. +
+ +## Step 9: Send the Quote **Instruction:** -- Click the blue **Create Quote** button at the bottom-right of the Quote Details dialog to submit and create the quote. +1. Click **Send quote**. +2. Check the recipient under **To**. They receive an email with a link to review and sign the quote. +3. Optionally, add **CC** addresses (up to 15). CC'd people get a copy when the quote is signed; they can't sign. +4. Open **Reminders & expiration** to change the defaults for this quote: + - **Send reminder emails**: when the first reminder goes out, how often after that, and how many reminders each signer gets (or **No limit**). + - **Expire the signature request**: makes the signing link stop working on the quote's **Valid until** date. Reminders stop on that date either way. +5. Click **Send quote**. -![Submit the completed quote](/img/turboquote/step-12.png) +![The Send quote dialog](/img/turboquote/new-quote/21-send-dialog.png) -
+![Reminders & expiration, with reminder emails turned on](/img/turboquote/new-quote/22-reminders.png) -## Step 13: Name Your Quote +These settings apply to this quote only. To change your team's defaults, go to **E-signature settings**. -Name the quote appropriately to identify it clearly for future reference and client communication. +
-**Instruction:** +## What Happens After You Send -- Click on the **Quote Name** text input field at the top of the Quote Details modal to begin typing the quote name. +Sending a quote creates a **TurboSign** signature request with the quote attached and emails it to the recipient. From there: -![Focus the quote name field](/img/turboquote/step-13a.png) +1. **The quote moves to Sent.** You'll find it on the **Sent** tab of the Quotes page. It can no longer be edited or renamed. +2. **The customer reviews and signs.** The email links to the quote, where the recipient reads it and signs to accept it. Any reminders you set go out on schedule until they sign or the quote's **Valid until** date passes. +3. **Signing accepts the quote.** As soon as the signature is complete, the quote moves to **Accepted** and counts towards your **Won**, **Monthly recurring** and **Win rate** cards. CC'd people get a copy of the signed quote. -![Enter the quote name](/img/turboquote/step-13b.png) +If things don't go to plan: + +- **The customer says no.** Choose **Mark as declined** from the quote's **⋮** menu. +- **You need to withdraw it.** Choose **Void quote**. Voiding the signature request in TurboSign voids the quote too. +- **The Valid until date passes first.** The quote moves to the **Expired** tab. Choose **Renew** to close it and make a new draft. See [Managing Your Quotes](./Managing-Your-Quotes.md#renewing-an-expired-quote).
## Summary -You've successfully created a new quote in TurboQuote! Here's a recap of what you accomplished: +You've created and sent a quote in TurboQuote! Here's a recap: + +1. Started a quote with **New quote** and picked the **contact** who signs it +2. Set the **quote details**: name, currency, quote type, term, valid-until date and tax +3. Added **products**, **bundles** and a **custom item**, with quantities, discounts and the right **price book** +4. **Previewed** the quote and **sent** it with reminders -1. Initiated a new quote from the TurboDocx home screen or TurboQuote quotes list -2. Created a new company record with industry classification -3. Added contact details including name and email -4. Selected the contact for the quote and submitted the final quote +Track it from the [Quotes page](./Managing-Your-Quotes.md): it moves to **Sent**, then to **Accepted** once your customer signs. -Your quote is now ready for you to add line items, pricing, and any additional details before sending it to your client. diff --git a/docs/TurboQuote/How-to-Configure-Quote-Numbering.md b/docs/TurboQuote/How-to-Configure-Quote-Numbering.md index 07475301..027a1809 100644 --- a/docs/TurboQuote/How-to-Configure-Quote-Numbering.md +++ b/docs/TurboQuote/How-to-Configure-Quote-Numbering.md @@ -1,6 +1,6 @@ --- title: How to Configure Quote Numbering -sidebar_position: 4 +sidebar_position: 9 description: Set a custom quote number format for your organization in TurboQuote, including prefix, year, month, digit padding, starting number, and reset cadence. keywords: - turboquote @@ -107,3 +107,15 @@ When the preview looks right, save. The **Save** button becomes active as soon a :::tip That's it Every new quote your organization creates from now on uses this format and picks up the next number in the sequence automatically. ::: + +
+ +## Changing numbering while you make a quote + +You don't have to leave a new quote to change the format. In the **Quote details** dialog of a new quote, the **Quote number** field shows the number the quote will get. Click **Edit numbering** next to it to open the same **Quote numbering** settings, with the next numbers shown as you edit. Saving there changes the numbering for your whole organization, exactly as in Settings. + +![The Quote numbering dialog opened from a new quote, with the next quote number](/img/turboquote/new-quote/06-numbering.png) + +:::tip From code +The API, the SDKs and n8n can read the next number without using it up, with `GET /v1/quotes/number-config/next` (`getNextQuoteNumber` in the SDKs). See the [TurboQuote SDK reference](../SDKs/quote.md). +::: diff --git a/docs/TurboQuote/How-to-Set-Your-Quote-Sender-Information.md b/docs/TurboQuote/How-to-Set-Your-Quote-Sender-Information.md index 8572c536..caca5a32 100644 --- a/docs/TurboQuote/How-to-Set-Your-Quote-Sender-Information.md +++ b/docs/TurboQuote/How-to-Set-Your-Quote-Sender-Information.md @@ -1,6 +1,6 @@ --- title: How to Set Your Quote Sender Information -sidebar_position: 6 +sidebar_position: 11 description: Set your organization's Sender Name, Sender Phone, and Sender Email so they appear as "Prepared by" on every TurboQuote quote. keywords: - turboquote diff --git a/docs/TurboQuote/Managing-Bundles.md b/docs/TurboQuote/Managing-Bundles.md new file mode 100644 index 00000000..fda8633e --- /dev/null +++ b/docs/TurboQuote/Managing-Bundles.md @@ -0,0 +1,100 @@ +--- +title: Managing Bundles +sidebar_position: 4 +description: Group products into TurboQuote bundles sold at one price, with item and bundle discounts, a price per billing type, and control over what customers see on the quote. +keywords: + - turboquote + - bundles + - product bundle + - bundle pricing + - bundle discount + - package pricing + - TurboDocx +--- + +# Managing Bundles + +A bundle is a set of products sold together at one price. When a rep adds a bundle to a quote, all of its items come with it. + +## What You'll Accomplish + +By the end of this guide, you will know how to: + +- 📦 **Read the Bundles page**, with a price for each billing type +- ⚙️ **Set what customers see**: the bundle's items, and each item's price +- 💲 **Price a bundle** with item discounts and a bundle discount +- 🗂️ **Hide, duplicate or delete** a bundle + +
+ +## The Bundles Page + +In the sidebar, open **TurboQuote** and click **Bundles**. Each bundle shows its category, SKU and description, how many items it has, and its price. A bundle that mixes billing types shows **one price per billing type**, for example a one-time amount and a monthly amount, rather than one total. + +Click **New bundle** to create one, or click a bundle's name to edit it. + +![The Bundles page in card view, with the New bundle button and a bundle priced one-time, monthly and yearly](/img/turboquote/bundles/01-bundles.png) + +
+ +## Step 1: Fill In the General Tab + +**Instruction:** + +1. Enter the **Name**, an optional **SKU** and a **Category** (type a name to create a new one). +2. Optionally add a **Description**, shown under the name in lists and on the bundle's quote line. +3. Choose what customers see: + - **Show the items to customers**: off, the quote shows one line with the bundle's name. On, the bundle's items are listed under it. + - **Show each item's price**: off, items are listed as **Included** and the bundle is priced as a whole. +4. **In the catalog**: hidden bundles can't be added to new quotes. +5. **Keep prices in sync with the products**: item list prices follow the catalog. A hidden product drops out of the price until it's shown again. + +![The General tab of a bundle with its customer visibility and catalog switches](/img/turboquote/bundles/02-bundle-general.png) + +:::note Hiding item prices on a mixed bundle +When a bundle's item prices are hidden, the quote still shows a total for each billing type. If the bundle mixes billing types, the customer can see how much of it is billed each way. The quote builder warns the rep when this happens. +::: + +
+ +## Step 2: Add Items and Set the Price + +**Instruction:** + +1. Open the **Items & pricing** tab. +2. Click **Add products** and pick the products to include. +3. For each item, set the **Quantity**, the **Billing**, and a **Discount / unit** as a percentage or an amount. The **Final / unit** and **Line total** update as you type. +4. Optionally enter a **Bundle discount** in the totals panel, as a percentage or an amount. +5. Click **Save changes**. + +![The Add products button on the Items & pricing tab](/img/turboquote/bundles/04-bundle-add-products.png) + +The price is built in three steps: the list price from the catalog, minus each item's discount, then the bundle discount comes off the total. When items bill differently, the bundle discount is shared across them the same way a quote does it. The **Bundle price** shows the result for each billing type, with how much the customer saves. + +![The totals panel: list total, after item discounts, bundle discount and the bundle price per billing type](/img/turboquote/bundles/03-bundle-items.png) + +:::tip Changing the currency +The **Currency** next to the item search sets the bundle's currency. Switching it clears an amount-based bundle discount, because that amount was in the old currency. A percentage carries over. +::: + +
+ +## Hide, Duplicate or Delete a Bundle + +- The **In the catalog** switch on each bundle hides it from new quotes without deleting it. The **All**, **In catalog** and **Hidden** tabs filter the list. +- Click the **⋮** button on a bundle to **Edit**, **Duplicate** or **Delete** it. **Duplicate** asks for the name of the copy, which starts as **Copy of …**. + +
+ +## Summary + +1. A bundle sells several products at **one price**, shown **per billing type** +2. Choose whether customers see the **items** and each **item's price** +3. The price is the **list price**, minus **item discounts**, minus the **bundle discount** +4. Use **In the catalog** to hide a bundle without deleting it + +## Related + +- [Adding a New Product](./Adding-a-New-Product.md) +- [Creating a New Quote](./Creating-a-New-Quote.md) +- [Bulk Importing from a Spreadsheet](./Bulk-Importing-from-a-Spreadsheet.md) diff --git a/docs/TurboQuote/Managing-Categories.md b/docs/TurboQuote/Managing-Categories.md new file mode 100644 index 00000000..39a20d28 --- /dev/null +++ b/docs/TurboQuote/Managing-Categories.md @@ -0,0 +1,88 @@ +--- +title: Managing Categories +sidebar_position: 7 +description: Create, rename and delete the TurboQuote categories that group products, bundles and price books and classify company industries. +keywords: + - turboquote + - categories + - product categories + - bundle categories + - price book categories + - industries + - TurboDocx +--- + +# Managing Categories + +Categories keep your catalog organised. Products, bundles and price books each have their own list of categories, and companies are classified by **industry**. You manage all four from one page. + +## What You'll Accomplish + +By the end of this guide, you will know how to: + +- 🗂️ **Switch between the four category lists** +- ➕ **Add a category** +- ✏️ **Rename or delete** a category, and why some can't be deleted + +
+ +## The Categories Page + +In the sidebar, open **TurboQuote** and click **Manage Categories**. The tabs switch between the four lists, each with a count: + +| Tab | What it's for | +|---|---| +| **Products** | Groups products in the catalog and on quotes. Quotes list items under these headings. | +| **Bundles** | Groups bundles in the catalog and in the **Add bundles** window. | +| **Price books** | Labels price books, like Standard, Partner or Enterprise. | +| **Industries** | Classifies the companies you sell to, like Healthcare or Finance. | + +The **Used by** column shows how many products, bundles, price books or companies use each category. Categories that come with TurboQuote are tagged **Default**. + +![The Categories page with the Products, Bundles, Price books and Industries tabs](/img/turboquote/categories/01-categories.png) + +![The Industries tab](/img/turboquote/categories/04-industries.png) + +
+ +## Add a Category + +**Instruction:** + +1. Open the tab for the kind of category you want. +2. Click **Add product category** (or **Add bundle category**, **Add price book category**, **Add industry**). +3. Enter the **Name** and click **Add category**. + +The category is available straight away. You can also create a category by typing a new name in the **Category** field of a product, bundle or price book. To add many at once, click **Import**; see [Bulk Importing from a Spreadsheet](./Bulk-Importing-from-a-Spreadsheet.md). + +![The Add product category dialog](/img/turboquote/categories/03-add-category.png) + +
+ +## Rename or Delete a Category + +Click the **⋮** button on a category and choose **Rename** or **Delete**. Renaming updates everything that uses the category. + +A category can't be deleted when: + +- it is a **Default** category, or +- something still uses it. Move those products, bundles, price books or companies to another category first. + +In both cases **Delete** is greyed out; hover the **ⓘ** icon to see why. + +![The category menu with Delete greyed out: "Default categories can't be deleted."](/img/turboquote/categories/02-category-actions.png) + +
+ +## Summary + +1. One page holds the **product**, **bundle**, **price book** and **industry** categories +2. **Add** a category from its tab, or by typing a new name on a product, bundle or price book +3. **Default** categories and categories **in use** can't be deleted + +## Related + +- [Adding a New Product](./Adding-a-New-Product.md) +- [Managing Bundles](./Managing-Bundles.md) +- [Managing Price Books](./Managing-Price-Books.md) +- [Managing Companies and Contacts](./Managing-Companies-and-Contacts.md) diff --git a/docs/TurboQuote/Managing-Companies-and-Contacts.md b/docs/TurboQuote/Managing-Companies-and-Contacts.md new file mode 100644 index 00000000..d3857b75 --- /dev/null +++ b/docs/TurboQuote/Managing-Companies-and-Contacts.md @@ -0,0 +1,107 @@ +--- +title: Managing Companies and Contacts +sidebar_position: 6 +description: Add and edit the companies you quote and the contacts who receive and sign your TurboQuote quotes, and see why a company or contact with open quotes can't be deleted. +keywords: + - turboquote + - companies + - contacts + - customers + - add company + - add contact + - company email + - TurboDocx +--- + +# Managing Companies and Contacts + +**Companies** are the businesses you quote. **Contacts** are the people at those companies who receive and sign your quotes. Every quote is made out to one contact. + +## What You'll Accomplish + +By the end of this guide, you will know how to: + +- 🏢 **Add a company** together with its first contact +- 👤 **Add and edit contacts** at a company +- ✏️ **Edit a company**, including its email address +- 🛑 **Understand why** a company or contact with open quotes can't be deleted + +
+ +## The Companies Page + +In the sidebar, open **TurboQuote** and click **Companies**. Each company shows its industry, email, phone, number of contacts and when it last had activity. Search by name, email, phone or location, or use **Filter** and **Sort** to narrow the list. + +![The Companies page with the New company button](/img/turboquote/companies/01-companies.png) + +
+ +## Add a Company + +**Instruction:** + +1. Click **New company**. +2. Enter the **Company name**, and optionally the **Industry**, **Email**, **Phone**, **City**, **State or province** and **Country**. +3. Under **Contacts**, fill in **Contact 1**: a **Name** and **Email** are required, **Title** and **Phone** are optional. A company needs at least one contact so you can send it quotes. Click **Add another contact** to add more. +4. Click **Create company**. + +![The New company dialog with the Contacts section](/img/turboquote/companies/07-new-company.png) + +:::tip Adding a company while making a quote +On the **Who is this quote for?** page of a new quote, click **Add new** and choose **New company** or **New contact**. The new contact is then picked for the quote. +::: + +
+ +## Add a Contact + +**Instruction:** + +1. Click a company's name to open its **Contacts** page. +2. Click **Add contact**. +3. Enter the **Name** and **Email**, and optionally the **Title** and **Phone**. +4. Click **Add contact**. + +![A company's Contacts page with the Add contact button](/img/turboquote/companies/02-company-contacts.png) + +![The Add contact dialog](/img/turboquote/companies/03-add-contact.png) + +To change a contact, click the **⋮** button on their row and choose **Edit contact**. To add many contacts at once, click **Import** on the Contacts page. + +
+ +## Edit a Company + +Click **Edit company** at the top of the company's page, or choose **Edit company** from the **⋮** menu on the Companies page. Here you can change the name, industry, **Email**, phone and location. + +![The Edit company dialog with the company email](/img/turboquote/companies/05-edit-company.png) + +
+ +## Deleting Companies and Contacts + +A company or contact that is on **open quotes** (drafts or sent quotes) can't be deleted. TurboQuote lists the quotes that are in the way, with a link to each one, so you can finish, void or move them first. + +![Can't delete Maria Anders: 1 open quote uses it](/img/turboquote/companies/04-contact-delete-blocked.png) + +![Can't delete Contoso Ltd: 2 open quotes use it](/img/turboquote/companies/06-company-delete-blocked.png) + +:::note A company keeps at least one contact +A company's **last contact** can't be deleted. Add another contact first, or delete the company instead. +::: + +The same rules apply through the API, the SDKs and n8n, which return a `409` error naming the reason. + +
+ +## Summary + +1. A **company** needs at least one **contact**, who receives and signs its quotes +2. Add contacts from the company's **Contacts** page, or while making a quote +3. Companies and contacts on **open quotes** can't be deleted, and a company always keeps its last contact + +## Related + +- [Creating a New Quote](./Creating-a-New-Quote.md) +- [Bulk Importing from a Spreadsheet](./Bulk-Importing-from-a-Spreadsheet.md) +- [Managing Categories](./Managing-Categories.md), for company industries diff --git a/docs/TurboQuote/Managing-Price-Books.md b/docs/TurboQuote/Managing-Price-Books.md new file mode 100644 index 00000000..a3380a0e --- /dev/null +++ b/docs/TurboQuote/Managing-Price-Books.md @@ -0,0 +1,93 @@ +--- +title: Managing Price Books +sidebar_position: 5 +description: Set up TurboQuote price books, discount tiers that reprice products on a quote, with a book-wide discount, per-product prices, a default book and validity dates. +keywords: + - turboquote + - price book + - price books + - discount tier + - partner pricing + - default price book + - TurboDocx +--- + +# Managing Price Books + +A price book is a discount tier, such as partner or nonprofit pricing. When a rep picks a price book on a quote, its products are repriced. Every new quote starts with your **default** price book. + +## What You'll Accomplish + +By the end of this guide, you will know how to: + +- 📚 **Read the Price books page** +- 💲 **Set a discount** for every product in a book, with validity dates +- 🏷️ **Give single products their own price**, and reset them +- ⭐ **Choose the default** price book + +
+ +## The Price Books Page + +In the sidebar, open **TurboQuote** and click **Price Books**. Each book shows its category, its discount, the dates it is valid, and whether it is offered on quotes. The default book is tagged **Default**. A book whose start date is in the future shows when it starts. + +Click **New price book** to create one, or click a book's name to edit it. + +![The Price books page with the New price book button](/img/turboquote/price-books/01-price-books.png) + +
+ +## Step 1: Fill In the General Tab + +**Instruction:** + +1. Enter the **Name**, a **Category** (type a name to create a new one) and an optional **Description**. +2. Enter the **Discount on every product**, as a percentage off the list price. +3. Set **Valid from**, and optionally **Valid to**. Leave **Valid to** empty to keep the book running. +4. Turn on **Default price book** to make new quotes start with this book. Only one book can be the default. +5. Leave **Offer it on quotes** on so reps can pick the book. Hidden books stay on the page, but reps can't pick them. + +![The General tab with the book-wide discount and the validity dates](/img/turboquote/price-books/03-price-book-general.png) + +
+ +## Step 2: Give Products Their Own Price (Optional) + +**Instruction:** + +1. Open the **Product prices** tab. The number on the tab counts the products with their own price. +2. Find a product and change its **Discount**, as a percentage or an amount. The **Final price** updates as you type. +3. Click **Save changes**. + +Every product follows the book's discount unless you give it its own here. A product with its own discount is tagged **Own price**; click the reset button at the end of its row to make it follow the book again. + +![The Product prices tab with one product on its own price](/img/turboquote/price-books/04-product-prices.png) + +To put every product back on the book's discount at once, click **Reset all** at the bottom of the list. + +![1 product has its own price, and the Reset all button](/img/turboquote/price-books/05-reset-all.png) + +
+ +## Duplicate or Delete a Price Book + +Click the **⋮** button on a book to **Edit**, **Duplicate**, **Make default** (or **Remove as default**) or **Delete** it. **Duplicate** asks for the name of the copy. + +The **default** book can't be deleted. Remove it as the default first, or make another book the default. + +![The menu of the default price book. Delete is greyed out with the reason "It's the default. Remove it as the default first."](/img/turboquote/price-books/02-default-book.png) + +
+ +## Summary + +1. A price book applies **one discount to every product**, between its valid dates +2. Give single products **their own price** on the **Product prices** tab, and **Reset all** to undo them +3. New quotes start with the **default** book, which can't be deleted +4. Turn off **Offer it on quotes** to hide a book from reps + +## Related + +- [Adding a New Product](./Adding-a-New-Product.md) +- [Creating a New Quote](./Creating-a-New-Quote.md) +- [Bulk Importing from a Spreadsheet](./Bulk-Importing-from-a-Spreadsheet.md) diff --git a/docs/TurboQuote/Managing-Your-Quotes.md b/docs/TurboQuote/Managing-Your-Quotes.md new file mode 100644 index 00000000..6b8fff36 --- /dev/null +++ b/docs/TurboQuote/Managing-Your-Quotes.md @@ -0,0 +1,177 @@ +--- +title: Managing Your Quotes +sidebar_position: 2 +description: Find, filter, sort and act on quotes from the TurboQuote Quotes page, read the summary cards, and renew, void, decline or delete a quote. +keywords: + - turboquote + - quotes list + - quote pipeline + - filter quotes + - sort quotes + - expired quote + - renew quote + - void quote + - delete quote + - TurboDocx +--- + +# Managing Your Quotes + +The **Quotes** page is where every quote you have made lives. It shows what your open pipeline is worth, lets you find any quote in a few keystrokes, and gives each quote a menu with the actions that make sense for its status. + +## What You'll Accomplish + +By the end of this guide, you will know how to: + +- 📊 **Read the summary cards** at the top of the page +- 🗂️ **Switch between status tabs**, including the **Expired** tab +- 🔎 **Search, filter and sort** the list +- 🃏 **Switch between table and card view** +- ⚙️ **Use the quote menu** to edit, rename, duplicate, renew, void, decline or delete a quote + +
+ +## Opening the Quotes Page + +TurboQuote has its own section in the left sidebar. Hover over the sidebar to expand it, then click **Quotes**. The same section holds **Companies**, **Products**, **Bundles**, **Price Books** and **Manage Categories**. + +![The TurboQuote section of the sidebar with Quotes, Companies, Products, Bundles, Price Books and Manage Categories](/img/turboquote/quotes/00-turboquote-menu.png) + +
+ +## The Summary Cards + +The row of cards at the top sums up the quotes on the page. They follow your tab, search and filters, so you can see what a single company or rep's pipeline is worth. + +| Card | What it counts | +|---|---| +| **Open pipeline** | The value of draft and sent quotes that have not expired | +| **Active quotes** | How many draft and sent quotes have not expired | +| **Won** | Accepted quotes, with the number declined beside it | +| **Monthly recurring** | Monthly-billed items on accepted quotes | +| **Win rate** | Quotes accepted, out of all quotes accepted or declined in the last 90 days | +| **Quotes this month** | Quotes created this calendar month | + +Amounts are shown in one currency. When the quotes on the page use two or more currencies, an **Amounts in** switch appears above the cards so you can pick which currency the cards add up. + +![The summary cards: Open pipeline, Active quotes, Won, Monthly recurring, Win rate and Quotes this month](/img/turboquote/quotes/01-summary-cards.png) + +
+ +## Status Tabs + +The tabs under the cards split your quotes by status, each with a count: **All**, **Drafts**, **Sent**, **Accepted**, **Declined**, **Voided** and **Expired**. + +![The status tabs with a count beside each one](/img/turboquote/quotes/02-status-tabs.png) + +:::info What "Expired" means +A quote is **expired** when it is a draft or a sent quote and its **Valid until** date has passed, or its signature request expired. An expired quote keeps its own status too, so a sent quote that ran out shows both a **Sent** and an **Expired** tag. Expired quotes are left out of the Open pipeline and Active quotes cards. +::: + +
+ +## Searching the List + +Type in the search box to find a quote by its **quote number**, **name**, **company** or **contact**. The list and the summary cards update as you type. + +![Searching for Contoso shows only Contoso's quotes, and the cards update to match](/img/turboquote/quotes/03-search.png) + +
+ +## Filtering the List + +Click **Filter** to narrow the list. You can combine any of these: + +- **Company**: one or more companies. A search box at the top finds companies and people quickly. +- **Currency**: one or more currencies. +- **Created by**: the people in your team who made the quotes, and **API keys** for quotes made through the API, the SDKs or an integration. +- **Valid until**: **This week**, **This month** or **Already passed**. + +Click **Done** to apply the filters. Each active filter shows as a chip above the list; remove a chip to drop that filter, or click **Clear** in the Filter menu to remove them all. + +![The Filter menu with its Company list](/img/turboquote/quotes/04-filter.png) + +![Further down the Filter menu: Created by, including API keys, and Valid until](/img/turboquote/quotes/05-filter-valid-until.png) + +
+ +## Sorting the List + +Click **Sort** and pick one of **Last updated**, **Date created**, **Total value**, **Valid until** or **Quote number**, then click **Done**. With **No sorting**, the newest quotes come first. + +![The Sort menu with No sorting, Last updated, Date created, Total value, Valid until and Quote number](/img/turboquote/quotes/06-sort.png) + +
+ +## Table and Card View + +The two buttons at the end of the toolbar switch between a **table** and **cards**. Your choice is remembered the next time you open the page. + +![The quotes shown as cards](/img/turboquote/quotes/07-card-view.png) + +
+ +## The Quote Menu + +Click the **⋮** button at the end of a row (or on a card) to open its menu. Only the actions that make sense for the quote's status appear. An action that can't be used right now stays in the menu, greyed out, with an **ⓘ** icon; hover it to see why. + +| Action | What it does | When it's available | +|---|---|---| +| **View & send** | Opens the quote preview, where you can download the PDF or send it | Always | +| **Edit** | Opens the quote in the builder | Always | +| **Rename** | Changes the quote's name | Drafts only. See [Renaming a Quote](./Renaming-a-Quote.md) | +| **Duplicate** | Makes a new draft with the same customer and line items. You name the copy; it starts as **Copy of …** | Always | +| **Renew** | Closes an expired quote and makes a new draft with a new **Valid until** date | Sent quotes that have expired | +| **Void quote** | Withdraws a sent quote | Sent quotes | +| **Mark as declined** | Records that the customer said no | Drafts and sent quotes | +| **Delete** | Deletes the quote | Drafts, declined and voided quotes | + +![The quote menu of a sent quote. Delete is greyed out with the reason "Sent quotes must be voided or declined first."](/img/turboquote/quotes/08-row-actions.png) + +:::caution Sent and accepted quotes can't be deleted +A **sent** quote must be voided or declined before you can delete it, and an **accepted** quote can't be deleted at all, because a customer has signed it. The same rule applies through the API, the SDKs and n8n, which return a `409` error for these quotes. +::: + +
+ +## Renewing an Expired Quote + +When a sent quote runs past its **Valid until** date, it moves to the **Expired** tab. To send the customer a fresh quote: + +**Instruction:** + +1. Open the **Expired** tab. +2. Click the **⋮** button on the quote and choose **Renew**. + +![The Expired tab with one expired sent quote](/img/turboquote/quotes/09-expired-tab.png) + +![The Renew action in the menu of an expired quote](/img/turboquote/quotes/10-renew.png) + +The **This quote has expired** dialog asks: + +- **New valid until**: the date the new draft is valid until. +- **What happened to the original?**: **Void it** (it ran out without an answer; it doesn't affect your win rate) or **Mark as declined** (the customer said no; it counts in your win rate), with a reason. The customer is emailed the reason. + +Click **Void and create new draft** (or **Decline and create new draft**). TurboQuote closes the original and opens a new draft with the same name, customer and line items, ready to review and send. + +If the quote's **signature request** has already expired, the original can no longer be signed, so the dialog only asks for the new date and the button reads **Create new draft**. + +:::tip Renewals keep the name +A renewal is the same deal re-issued, so it keeps the original quote's name. Only **Duplicate** names the new quote **Copy of …**. +::: + +
+ +## Summary + +1. The **summary cards** add up the quotes you are looking at +2. **Status tabs** split quotes by status; **Expired** collects quotes past their Valid until date +3. **Search**, **Filter** and **Sort** find any quote quickly +4. The **⋮ menu** offers only the actions that fit the quote's status +5. **Renew** turns an expired quote into a new draft in one step + +## Related + +- [Creating a New Quote](./Creating-a-New-Quote.md) +- [Renaming a Quote](./Renaming-a-Quote.md) +- [TurboQuote SDK reference](../SDKs/quote.md), for listing, filtering and sorting quotes from code diff --git a/docs/TurboQuote/Prepared-By-and-Sender-Identity.md b/docs/TurboQuote/Prepared-By-and-Sender-Identity.md index afe07b17..596f3fb5 100644 --- a/docs/TurboQuote/Prepared-By-and-Sender-Identity.md +++ b/docs/TurboQuote/Prepared-By-and-Sender-Identity.md @@ -1,6 +1,6 @@ --- title: 'Prepared By & Sender Identity' -sidebar_position: 5 +sidebar_position: 10 description: 'Configure TurboQuote sender identity: manage "Prepared by" name and email on quotes in the UI, API, SDKs, and n8n.' keywords: - turboquote diff --git a/docs/TurboQuote/Renaming-a-Quote.md b/docs/TurboQuote/Renaming-a-Quote.md index bb101340..c8a9b05e 100644 --- a/docs/TurboQuote/Renaming-a-Quote.md +++ b/docs/TurboQuote/Renaming-a-Quote.md @@ -1,6 +1,6 @@ --- title: Renaming a Quote -sidebar_position: 7 +sidebar_position: 12 description: Rename a draft quote from the quotes list or the quote page, and understand how a quote's name reaches the signer when you send it for signature. keywords: - turboquote @@ -43,12 +43,14 @@ Two ordinary actions produce a name you probably don't want a client to read: | How you got here | The name you end up with | |---|---| -| You **duplicated** a quote to reuse its line items | `Copy of Acme Q3 Proposal` | +| You **duplicated** a quote and kept the suggested name | `Copy of Acme Q3 Proposal` | | You duplicated the copy again | `Copy of Copy of Acme Q3 Proposal` | -If you send either of those without renaming, `Copy of Acme Q3 Proposal` is the title on the -signature request your client receives. Renaming takes a couple of seconds and happens before the -send, so it never reaches them. +When you choose **Duplicate**, TurboQuote asks for the **name of the copy** and suggests +`Copy of …`. Type the real name there and you are done. If you keep the suggestion and send the +quote without renaming, `Copy of Acme Q3 Proposal` is the title on the signature request your +client receives. Renaming takes a couple of seconds and happens before the send, so it never +reaches them. :::tip Renewals don't do this Renewing an expired quote is different from duplicating one. A renewal is the **same deal @@ -104,7 +106,7 @@ A few rules apply wherever you rename: ## When renaming is unavailable The **Rename** option is visible but greyed out once a quote leaves draft status — after it has -been sent, accepted, declined, or voided. This is deliberate: the signature request has already +been sent, accepted, declined, or voided. Hover the **ⓘ** icon next to it to see why. This is deliberate: the signature request has already been delivered under the current name, and quietly changing the title of a document someone has already received would be misleading. @@ -123,7 +125,7 @@ Here's what to remember: 1. A quote's name becomes the **signature document's name** when you send it 2. Rename from the **quote page header** or the **⋮ menu** in the quotes list -3. Duplicates arrive as `Copy of …` — rename them before sending +3. Duplicates are named `Copy of …` unless you name the copy — rename them before sending 4. Renewals keep the original name and never accumulate `Copy of` prefixes 5. Renaming is **draft-only**; after sending, void and re-send instead diff --git a/docs/Welcome-to-TurboDocx.md b/docs/Welcome-to-TurboDocx.md index 7893144f..c9ba352f 100644 --- a/docs/Welcome-to-TurboDocx.md +++ b/docs/Welcome-to-TurboDocx.md @@ -48,8 +48,10 @@ TurboSign sends documents for e-signature, tracks who has signed, and keeps the TurboQuote builds sales quotes and proposals from a product catalog, price books, and line items. -- [Creating a New Quote](./TurboQuote/Creating-a-New-Quote.md): build your first quote. -- [Adding a New Product](./TurboQuote/Adding-a-New-Product.md) and [Bulk Importing from a Spreadsheet](./TurboQuote/Bulk-Importing-from-a-Spreadsheet.md): populate your product catalog. +- [Creating a New Quote](./TurboQuote/Creating-a-New-Quote.md): build your first quote and send it for signature. +- [Managing Your Quotes](./TurboQuote/Managing-Your-Quotes.md): find, filter, renew, void, and delete quotes. +- [Adding a New Product](./TurboQuote/Adding-a-New-Product.md), [Managing Bundles](./TurboQuote/Managing-Bundles.md), [Managing Price Books](./TurboQuote/Managing-Price-Books.md), and [Bulk Importing from a Spreadsheet](./TurboQuote/Bulk-Importing-from-a-Spreadsheet.md): populate your catalog. +- [Managing Companies and Contacts](./TurboQuote/Managing-Companies-and-Contacts.md): keep your customers and the people who sign up to date. ## Build on the API and SDKs diff --git a/static/img/turboquote/bundles/01-bundles.png b/static/img/turboquote/bundles/01-bundles.png new file mode 100644 index 00000000..c4a66686 Binary files /dev/null and b/static/img/turboquote/bundles/01-bundles.png differ diff --git a/static/img/turboquote/bundles/02-bundle-general.png b/static/img/turboquote/bundles/02-bundle-general.png new file mode 100644 index 00000000..0e1c39b1 Binary files /dev/null and b/static/img/turboquote/bundles/02-bundle-general.png differ diff --git a/static/img/turboquote/bundles/03-bundle-items.png b/static/img/turboquote/bundles/03-bundle-items.png new file mode 100644 index 00000000..49f09f1d Binary files /dev/null and b/static/img/turboquote/bundles/03-bundle-items.png differ diff --git a/static/img/turboquote/bundles/04-bundle-add-products.png b/static/img/turboquote/bundles/04-bundle-add-products.png new file mode 100644 index 00000000..a912c6fe Binary files /dev/null and b/static/img/turboquote/bundles/04-bundle-add-products.png differ diff --git a/static/img/turboquote/categories/01-categories.png b/static/img/turboquote/categories/01-categories.png new file mode 100644 index 00000000..6074c499 Binary files /dev/null and b/static/img/turboquote/categories/01-categories.png differ diff --git a/static/img/turboquote/categories/02-category-actions.png b/static/img/turboquote/categories/02-category-actions.png new file mode 100644 index 00000000..82371ced Binary files /dev/null and b/static/img/turboquote/categories/02-category-actions.png differ diff --git a/static/img/turboquote/categories/03-add-category.png b/static/img/turboquote/categories/03-add-category.png new file mode 100644 index 00000000..0daa2a78 Binary files /dev/null and b/static/img/turboquote/categories/03-add-category.png differ diff --git a/static/img/turboquote/categories/04-industries.png b/static/img/turboquote/categories/04-industries.png new file mode 100644 index 00000000..37c442bb Binary files /dev/null and b/static/img/turboquote/categories/04-industries.png differ diff --git a/static/img/turboquote/companies/01-companies.png b/static/img/turboquote/companies/01-companies.png new file mode 100644 index 00000000..783868dd Binary files /dev/null and b/static/img/turboquote/companies/01-companies.png differ diff --git a/static/img/turboquote/companies/02-company-contacts.png b/static/img/turboquote/companies/02-company-contacts.png new file mode 100644 index 00000000..6f902eb2 Binary files /dev/null and b/static/img/turboquote/companies/02-company-contacts.png differ diff --git a/static/img/turboquote/companies/03-add-contact.png b/static/img/turboquote/companies/03-add-contact.png new file mode 100644 index 00000000..37830e25 Binary files /dev/null and b/static/img/turboquote/companies/03-add-contact.png differ diff --git a/static/img/turboquote/companies/04-contact-delete-blocked.png b/static/img/turboquote/companies/04-contact-delete-blocked.png new file mode 100644 index 00000000..44ef1271 Binary files /dev/null and b/static/img/turboquote/companies/04-contact-delete-blocked.png differ diff --git a/static/img/turboquote/companies/05-edit-company.png b/static/img/turboquote/companies/05-edit-company.png new file mode 100644 index 00000000..457b34c0 Binary files /dev/null and b/static/img/turboquote/companies/05-edit-company.png differ diff --git a/static/img/turboquote/companies/06-company-delete-blocked.png b/static/img/turboquote/companies/06-company-delete-blocked.png new file mode 100644 index 00000000..95ff5a66 Binary files /dev/null and b/static/img/turboquote/companies/06-company-delete-blocked.png differ diff --git a/static/img/turboquote/companies/07-new-company.png b/static/img/turboquote/companies/07-new-company.png new file mode 100644 index 00000000..32f6a527 Binary files /dev/null and b/static/img/turboquote/companies/07-new-company.png differ diff --git a/static/img/turboquote/new-quote/01-new-quote-button.png b/static/img/turboquote/new-quote/01-new-quote-button.png new file mode 100644 index 00000000..cb57d387 Binary files /dev/null and b/static/img/turboquote/new-quote/01-new-quote-button.png differ diff --git a/static/img/turboquote/new-quote/02-pick-contact.png b/static/img/turboquote/new-quote/02-pick-contact.png new file mode 100644 index 00000000..7e4e6f44 Binary files /dev/null and b/static/img/turboquote/new-quote/02-pick-contact.png differ diff --git a/static/img/turboquote/new-quote/03-add-new.png b/static/img/turboquote/new-quote/03-add-new.png new file mode 100644 index 00000000..e2e44312 Binary files /dev/null and b/static/img/turboquote/new-quote/03-add-new.png differ diff --git a/static/img/turboquote/new-quote/04-quote-details.png b/static/img/turboquote/new-quote/04-quote-details.png new file mode 100644 index 00000000..fcc18547 Binary files /dev/null and b/static/img/turboquote/new-quote/04-quote-details.png differ diff --git a/static/img/turboquote/new-quote/05-quote-type.png b/static/img/turboquote/new-quote/05-quote-type.png new file mode 100644 index 00000000..53afb793 Binary files /dev/null and b/static/img/turboquote/new-quote/05-quote-type.png differ diff --git a/static/img/turboquote/new-quote/06-numbering.png b/static/img/turboquote/new-quote/06-numbering.png new file mode 100644 index 00000000..b609324d Binary files /dev/null and b/static/img/turboquote/new-quote/06-numbering.png differ diff --git a/static/img/turboquote/new-quote/07-create-quote.png b/static/img/turboquote/new-quote/07-create-quote.png new file mode 100644 index 00000000..b4d04335 Binary files /dev/null and b/static/img/turboquote/new-quote/07-create-quote.png differ diff --git a/static/img/turboquote/new-quote/08-builder-empty.png b/static/img/turboquote/new-quote/08-builder-empty.png new file mode 100644 index 00000000..ea66f83c Binary files /dev/null and b/static/img/turboquote/new-quote/08-builder-empty.png differ diff --git a/static/img/turboquote/new-quote/09-add-products.png b/static/img/turboquote/new-quote/09-add-products.png new file mode 100644 index 00000000..083147b3 Binary files /dev/null and b/static/img/turboquote/new-quote/09-add-products.png differ diff --git a/static/img/turboquote/new-quote/10-line-items.png b/static/img/turboquote/new-quote/10-line-items.png new file mode 100644 index 00000000..44c3c4dd Binary files /dev/null and b/static/img/turboquote/new-quote/10-line-items.png differ diff --git a/static/img/turboquote/new-quote/11-quote-total.png b/static/img/turboquote/new-quote/11-quote-total.png new file mode 100644 index 00000000..f9fb71b1 Binary files /dev/null and b/static/img/turboquote/new-quote/11-quote-total.png differ diff --git a/static/img/turboquote/new-quote/11a-price-book-button.png b/static/img/turboquote/new-quote/11a-price-book-button.png new file mode 100644 index 00000000..925ccef4 Binary files /dev/null and b/static/img/turboquote/new-quote/11a-price-book-button.png differ diff --git a/static/img/turboquote/new-quote/11b-price-book-dialog.png b/static/img/turboquote/new-quote/11b-price-book-dialog.png new file mode 100644 index 00000000..569f57a9 Binary files /dev/null and b/static/img/turboquote/new-quote/11b-price-book-dialog.png differ diff --git a/static/img/turboquote/new-quote/12-custom-item.png b/static/img/turboquote/new-quote/12-custom-item.png new file mode 100644 index 00000000..7d3f8a09 Binary files /dev/null and b/static/img/turboquote/new-quote/12-custom-item.png differ diff --git a/static/img/turboquote/new-quote/13-custom-item-pricing.png b/static/img/turboquote/new-quote/13-custom-item-pricing.png new file mode 100644 index 00000000..c6d8b2ea Binary files /dev/null and b/static/img/turboquote/new-quote/13-custom-item-pricing.png differ diff --git a/static/img/turboquote/new-quote/14-custom-item-images.png b/static/img/turboquote/new-quote/14-custom-item-images.png new file mode 100644 index 00000000..7880bbaa Binary files /dev/null and b/static/img/turboquote/new-quote/14-custom-item-images.png differ diff --git a/static/img/turboquote/new-quote/15-custom-item-row.png b/static/img/turboquote/new-quote/15-custom-item-row.png new file mode 100644 index 00000000..46f9fbff Binary files /dev/null and b/static/img/turboquote/new-quote/15-custom-item-row.png differ diff --git a/static/img/turboquote/new-quote/16-custom-item-menu.png b/static/img/turboquote/new-quote/16-custom-item-menu.png new file mode 100644 index 00000000..556e8857 Binary files /dev/null and b/static/img/turboquote/new-quote/16-custom-item-menu.png differ diff --git a/static/img/turboquote/new-quote/17-add-bundles.png b/static/img/turboquote/new-quote/17-add-bundles.png new file mode 100644 index 00000000..1d4c2133 Binary files /dev/null and b/static/img/turboquote/new-quote/17-add-bundles.png differ diff --git a/static/img/turboquote/new-quote/18-edit-details.png b/static/img/turboquote/new-quote/18-edit-details.png new file mode 100644 index 00000000..e5886aa6 Binary files /dev/null and b/static/img/turboquote/new-quote/18-edit-details.png differ diff --git a/static/img/turboquote/new-quote/19-preview-send-button.png b/static/img/turboquote/new-quote/19-preview-send-button.png new file mode 100644 index 00000000..682c12a3 Binary files /dev/null and b/static/img/turboquote/new-quote/19-preview-send-button.png differ diff --git a/static/img/turboquote/new-quote/20-preview.png b/static/img/turboquote/new-quote/20-preview.png new file mode 100644 index 00000000..345d35a0 Binary files /dev/null and b/static/img/turboquote/new-quote/20-preview.png differ diff --git a/static/img/turboquote/new-quote/21-send-dialog.png b/static/img/turboquote/new-quote/21-send-dialog.png new file mode 100644 index 00000000..6244555d Binary files /dev/null and b/static/img/turboquote/new-quote/21-send-dialog.png differ diff --git a/static/img/turboquote/new-quote/22-reminders.png b/static/img/turboquote/new-quote/22-reminders.png new file mode 100644 index 00000000..20d0ed92 Binary files /dev/null and b/static/img/turboquote/new-quote/22-reminders.png differ diff --git a/static/img/turboquote/price-books/01-price-books.png b/static/img/turboquote/price-books/01-price-books.png new file mode 100644 index 00000000..370e33be Binary files /dev/null and b/static/img/turboquote/price-books/01-price-books.png differ diff --git a/static/img/turboquote/price-books/02-default-book.png b/static/img/turboquote/price-books/02-default-book.png new file mode 100644 index 00000000..f33c5e9a Binary files /dev/null and b/static/img/turboquote/price-books/02-default-book.png differ diff --git a/static/img/turboquote/price-books/03-price-book-general.png b/static/img/turboquote/price-books/03-price-book-general.png new file mode 100644 index 00000000..de65cf73 Binary files /dev/null and b/static/img/turboquote/price-books/03-price-book-general.png differ diff --git a/static/img/turboquote/price-books/04-product-prices.png b/static/img/turboquote/price-books/04-product-prices.png new file mode 100644 index 00000000..6e1b46cc Binary files /dev/null and b/static/img/turboquote/price-books/04-product-prices.png differ diff --git a/static/img/turboquote/price-books/05-reset-all.png b/static/img/turboquote/price-books/05-reset-all.png new file mode 100644 index 00000000..a20ce90b Binary files /dev/null and b/static/img/turboquote/price-books/05-reset-all.png differ diff --git a/static/img/turboquote/product-step-01.png b/static/img/turboquote/product-step-01.png deleted file mode 100644 index 1cfe7a91..00000000 Binary files a/static/img/turboquote/product-step-01.png and /dev/null differ diff --git a/static/img/turboquote/product-step-02.png b/static/img/turboquote/product-step-02.png deleted file mode 100644 index bd5023b9..00000000 Binary files a/static/img/turboquote/product-step-02.png and /dev/null differ diff --git a/static/img/turboquote/product-step-03.png b/static/img/turboquote/product-step-03.png deleted file mode 100644 index 633c4b71..00000000 Binary files a/static/img/turboquote/product-step-03.png and /dev/null differ diff --git a/static/img/turboquote/product-step-04.png b/static/img/turboquote/product-step-04.png deleted file mode 100644 index 2d35d74c..00000000 Binary files a/static/img/turboquote/product-step-04.png and /dev/null differ diff --git a/static/img/turboquote/product-step-05.png b/static/img/turboquote/product-step-05.png deleted file mode 100644 index 9cc4826f..00000000 Binary files a/static/img/turboquote/product-step-05.png and /dev/null differ diff --git a/static/img/turboquote/product-step-06.png b/static/img/turboquote/product-step-06.png deleted file mode 100644 index a86e3f3a..00000000 Binary files a/static/img/turboquote/product-step-06.png and /dev/null differ diff --git a/static/img/turboquote/product-step-07.png b/static/img/turboquote/product-step-07.png deleted file mode 100644 index 096bd93e..00000000 Binary files a/static/img/turboquote/product-step-07.png and /dev/null differ diff --git a/static/img/turboquote/product-step-08.png b/static/img/turboquote/product-step-08.png deleted file mode 100644 index bacfa7f9..00000000 Binary files a/static/img/turboquote/product-step-08.png and /dev/null differ diff --git a/static/img/turboquote/product-step-09.png b/static/img/turboquote/product-step-09.png deleted file mode 100644 index 999fcccb..00000000 Binary files a/static/img/turboquote/product-step-09.png and /dev/null differ diff --git a/static/img/turboquote/product-step-10.png b/static/img/turboquote/product-step-10.png deleted file mode 100644 index a4ac0c32..00000000 Binary files a/static/img/turboquote/product-step-10.png and /dev/null differ diff --git a/static/img/turboquote/product-step-11.png b/static/img/turboquote/product-step-11.png deleted file mode 100644 index 6514b671..00000000 Binary files a/static/img/turboquote/product-step-11.png and /dev/null differ diff --git a/static/img/turboquote/product-step-12.png b/static/img/turboquote/product-step-12.png deleted file mode 100644 index 26c58050..00000000 Binary files a/static/img/turboquote/product-step-12.png and /dev/null differ diff --git a/static/img/turboquote/product-step-13.png b/static/img/turboquote/product-step-13.png deleted file mode 100644 index 44a52ac9..00000000 Binary files a/static/img/turboquote/product-step-13.png and /dev/null differ diff --git a/static/img/turboquote/products/01-products.png b/static/img/turboquote/products/01-products.png new file mode 100644 index 00000000..2f97d2f5 Binary files /dev/null and b/static/img/turboquote/products/01-products.png differ diff --git a/static/img/turboquote/products/02-catalog-tabs.png b/static/img/turboquote/products/02-catalog-tabs.png new file mode 100644 index 00000000..966a86fb Binary files /dev/null and b/static/img/turboquote/products/02-catalog-tabs.png differ diff --git a/static/img/turboquote/products/03-new-product-general.png b/static/img/turboquote/products/03-new-product-general.png new file mode 100644 index 00000000..863a1e28 Binary files /dev/null and b/static/img/turboquote/products/03-new-product-general.png differ diff --git a/static/img/turboquote/products/04-new-product-pricing.png b/static/img/turboquote/products/04-new-product-pricing.png new file mode 100644 index 00000000..494ae34e Binary files /dev/null and b/static/img/turboquote/products/04-new-product-pricing.png differ diff --git a/static/img/turboquote/products/05-new-product-images.png b/static/img/turboquote/products/05-new-product-images.png new file mode 100644 index 00000000..0aa6f1df Binary files /dev/null and b/static/img/turboquote/products/05-new-product-images.png differ diff --git a/static/img/turboquote/products/06-product-actions.png b/static/img/turboquote/products/06-product-actions.png new file mode 100644 index 00000000..af933609 Binary files /dev/null and b/static/img/turboquote/products/06-product-actions.png differ diff --git a/static/img/turboquote/products/07-duplicate.png b/static/img/turboquote/products/07-duplicate.png new file mode 100644 index 00000000..133c3f70 Binary files /dev/null and b/static/img/turboquote/products/07-duplicate.png differ diff --git a/static/img/turboquote/quotes/00-turboquote-menu.png b/static/img/turboquote/quotes/00-turboquote-menu.png new file mode 100644 index 00000000..ca7cc765 Binary files /dev/null and b/static/img/turboquote/quotes/00-turboquote-menu.png differ diff --git a/static/img/turboquote/quotes/01-summary-cards.png b/static/img/turboquote/quotes/01-summary-cards.png new file mode 100644 index 00000000..ef2f3028 Binary files /dev/null and b/static/img/turboquote/quotes/01-summary-cards.png differ diff --git a/static/img/turboquote/quotes/02-status-tabs.png b/static/img/turboquote/quotes/02-status-tabs.png new file mode 100644 index 00000000..e63bdf81 Binary files /dev/null and b/static/img/turboquote/quotes/02-status-tabs.png differ diff --git a/static/img/turboquote/quotes/03-search.png b/static/img/turboquote/quotes/03-search.png new file mode 100644 index 00000000..16a7c4d0 Binary files /dev/null and b/static/img/turboquote/quotes/03-search.png differ diff --git a/static/img/turboquote/quotes/04-filter.png b/static/img/turboquote/quotes/04-filter.png new file mode 100644 index 00000000..330deb81 Binary files /dev/null and b/static/img/turboquote/quotes/04-filter.png differ diff --git a/static/img/turboquote/quotes/05-filter-valid-until.png b/static/img/turboquote/quotes/05-filter-valid-until.png new file mode 100644 index 00000000..72075ecd Binary files /dev/null and b/static/img/turboquote/quotes/05-filter-valid-until.png differ diff --git a/static/img/turboquote/quotes/06-sort.png b/static/img/turboquote/quotes/06-sort.png new file mode 100644 index 00000000..e8adde2e Binary files /dev/null and b/static/img/turboquote/quotes/06-sort.png differ diff --git a/static/img/turboquote/quotes/07-card-view.png b/static/img/turboquote/quotes/07-card-view.png new file mode 100644 index 00000000..9cc05128 Binary files /dev/null and b/static/img/turboquote/quotes/07-card-view.png differ diff --git a/static/img/turboquote/quotes/08-row-actions.png b/static/img/turboquote/quotes/08-row-actions.png new file mode 100644 index 00000000..7548ed86 Binary files /dev/null and b/static/img/turboquote/quotes/08-row-actions.png differ diff --git a/static/img/turboquote/quotes/09-expired-tab.png b/static/img/turboquote/quotes/09-expired-tab.png new file mode 100644 index 00000000..bf2d42cd Binary files /dev/null and b/static/img/turboquote/quotes/09-expired-tab.png differ diff --git a/static/img/turboquote/quotes/10-renew.png b/static/img/turboquote/quotes/10-renew.png new file mode 100644 index 00000000..f84fa2c5 Binary files /dev/null and b/static/img/turboquote/quotes/10-renew.png differ diff --git a/static/img/turboquote/step-01.png b/static/img/turboquote/step-01.png deleted file mode 100644 index 5fd432e4..00000000 Binary files a/static/img/turboquote/step-01.png and /dev/null differ diff --git a/static/img/turboquote/step-02.png b/static/img/turboquote/step-02.png deleted file mode 100644 index 19ba30a9..00000000 Binary files a/static/img/turboquote/step-02.png and /dev/null differ diff --git a/static/img/turboquote/step-03.png b/static/img/turboquote/step-03.png deleted file mode 100644 index 1f62a14a..00000000 Binary files a/static/img/turboquote/step-03.png and /dev/null differ diff --git a/static/img/turboquote/step-04.png b/static/img/turboquote/step-04.png deleted file mode 100644 index 1a56fac4..00000000 Binary files a/static/img/turboquote/step-04.png and /dev/null differ diff --git a/static/img/turboquote/step-05.png b/static/img/turboquote/step-05.png deleted file mode 100644 index be18ec7d..00000000 Binary files a/static/img/turboquote/step-05.png and /dev/null differ diff --git a/static/img/turboquote/step-06.png b/static/img/turboquote/step-06.png deleted file mode 100644 index 8a5e757d..00000000 Binary files a/static/img/turboquote/step-06.png and /dev/null differ diff --git a/static/img/turboquote/step-07.png b/static/img/turboquote/step-07.png deleted file mode 100644 index 62582ac3..00000000 Binary files a/static/img/turboquote/step-07.png and /dev/null differ diff --git a/static/img/turboquote/step-08a.png b/static/img/turboquote/step-08a.png deleted file mode 100644 index 4cf733b5..00000000 Binary files a/static/img/turboquote/step-08a.png and /dev/null differ diff --git a/static/img/turboquote/step-08b.png b/static/img/turboquote/step-08b.png deleted file mode 100644 index feede3ba..00000000 Binary files a/static/img/turboquote/step-08b.png and /dev/null differ diff --git a/static/img/turboquote/step-09.png b/static/img/turboquote/step-09.png deleted file mode 100644 index a29378f7..00000000 Binary files a/static/img/turboquote/step-09.png and /dev/null differ diff --git a/static/img/turboquote/step-10.png b/static/img/turboquote/step-10.png deleted file mode 100644 index 290f63d0..00000000 Binary files a/static/img/turboquote/step-10.png and /dev/null differ diff --git a/static/img/turboquote/step-11.png b/static/img/turboquote/step-11.png deleted file mode 100644 index 346a0109..00000000 Binary files a/static/img/turboquote/step-11.png and /dev/null differ diff --git a/static/img/turboquote/step-12.png b/static/img/turboquote/step-12.png deleted file mode 100644 index 55850014..00000000 Binary files a/static/img/turboquote/step-12.png and /dev/null differ diff --git a/static/img/turboquote/step-13a.png b/static/img/turboquote/step-13a.png deleted file mode 100644 index 90871a3c..00000000 Binary files a/static/img/turboquote/step-13a.png and /dev/null differ diff --git a/static/img/turboquote/step-13b.png b/static/img/turboquote/step-13b.png deleted file mode 100644 index 3fdc2f33..00000000 Binary files a/static/img/turboquote/step-13b.png and /dev/null differ diff --git a/static/img/turboquote_bulk_import/00-import-button.png b/static/img/turboquote_bulk_import/00-import-button.png new file mode 100644 index 00000000..a9f06e4f Binary files /dev/null and b/static/img/turboquote_bulk_import/00-import-button.png differ diff --git a/static/img/turboquote_bulk_import/01-upload.png b/static/img/turboquote_bulk_import/01-upload.png new file mode 100644 index 00000000..134abfd3 Binary files /dev/null and b/static/img/turboquote_bulk_import/01-upload.png differ diff --git a/static/img/turboquote_bulk_import/01_products_import_button.png b/static/img/turboquote_bulk_import/01_products_import_button.png deleted file mode 100644 index efde481a..00000000 Binary files a/static/img/turboquote_bulk_import/01_products_import_button.png and /dev/null differ diff --git a/static/img/turboquote_bulk_import/02-match-columns.png b/static/img/turboquote_bulk_import/02-match-columns.png new file mode 100644 index 00000000..92300b47 Binary files /dev/null and b/static/img/turboquote_bulk_import/02-match-columns.png differ diff --git a/static/img/turboquote_bulk_import/02_upload_step.png b/static/img/turboquote_bulk_import/02_upload_step.png deleted file mode 100644 index 5e397bff..00000000 Binary files a/static/img/turboquote_bulk_import/02_upload_step.png and /dev/null differ diff --git a/static/img/turboquote_bulk_import/03-contact-columns.png b/static/img/turboquote_bulk_import/03-contact-columns.png new file mode 100644 index 00000000..79880f85 Binary files /dev/null and b/static/img/turboquote_bulk_import/03-contact-columns.png differ diff --git a/static/img/turboquote_bulk_import/03_map_columns.png b/static/img/turboquote_bulk_import/03_map_columns.png deleted file mode 100644 index cd6013e6..00000000 Binary files a/static/img/turboquote_bulk_import/03_map_columns.png and /dev/null differ diff --git a/static/img/turboquote_bulk_import/04-review.png b/static/img/turboquote_bulk_import/04-review.png new file mode 100644 index 00000000..96887dcc Binary files /dev/null and b/static/img/turboquote_bulk_import/04-review.png differ diff --git a/static/img/turboquote_bulk_import/04_review_import.png b/static/img/turboquote_bulk_import/04_review_import.png deleted file mode 100644 index 93e4140e..00000000 Binary files a/static/img/turboquote_bulk_import/04_review_import.png and /dev/null differ diff --git a/static/img/turboquote_bulk_import/05-products-upload.png b/static/img/turboquote_bulk_import/05-products-upload.png new file mode 100644 index 00000000..e289bbc5 Binary files /dev/null and b/static/img/turboquote_bulk_import/05-products-upload.png differ diff --git a/static/img/turboquote_bulk_import/05_companies_import_button.png b/static/img/turboquote_bulk_import/05_companies_import_button.png deleted file mode 100644 index 9e6cc027..00000000 Binary files a/static/img/turboquote_bulk_import/05_companies_import_button.png and /dev/null differ diff --git a/static/img/turboquote_bulk_import/06_companies_map.png b/static/img/turboquote_bulk_import/06_companies_map.png deleted file mode 100644 index 4bc3b01c..00000000 Binary files a/static/img/turboquote_bulk_import/06_companies_map.png and /dev/null differ diff --git a/static/img/turboquote_bulk_import/07_companies_review.png b/static/img/turboquote_bulk_import/07_companies_review.png deleted file mode 100644 index 06296fff..00000000 Binary files a/static/img/turboquote_bulk_import/07_companies_review.png and /dev/null differ