Vendor Offers & My Offers · two tabs each · nothing built yet

Individual and group offers

The admin’s Vendor Offers page and the facility’s My Offers page each get two tabs. Individual Offers is today’s list, limited to offers on one listing. Group Offers lists the offers on more than one listing, one row per offer. Which tab an offer belongs to is its bundle’s item_count.

Pages
2Vendor Offers · My Offers
Tabs
2on each page
New endpoints
2group offers, and one offer’s items
Reused
2app-tabs, cs-data-table

The two pagesdifferent components today

PageWhoComponentAPI today
Vendor Offersadminsvendor-offers/marketplace-offers/listGET /marketplace/sell-to-capexpert
My Offersfacilities, management groupsoffers/facility-vendor-offer/my-offer/listGET /vendor-offer/my-offers

A vendor’s own My Offers is not part of this: it lists one row per offer already, with its item count (V1). Whether vendors get the same two tabs is Q8.

Tab 1 · Individual Offersitem_count = 1

Today’s list, with the same columns, filters, row actions and row expansion, limited to offers on a single listing.

  1. T1Rows are the listings that have at least one individual offer. A listing whose only offers are group offers does not appear here.rows
  2. T2On each row, the offer count, the offer status, the PA number and the vendor offers in the expansion count individual offers only.row
  3. T3The status is computed in SQL over the listing’s individual offers, for display, filter and sort. The stored counter_offer_status covers every offer on the listing, group offers included, so this tab cannot use it as it is.status
  4. T4A listing that is also in a live group offer carries an “In a group offer” badge that opens the Group tab on that offer. A group offer’s PA locks the listing, and accepting an individual offer on it is then refused.badge
  5. T5The summary line — offers, awaiting response, total offer value — counts individual offers only.summary

Tab 2 · Group Offersitem_count above 1 · one row per offer

ColumnShows
OfferThe vendor, and the item count: “5 items”.
FacilityThe seller facility and its location. Every item belongs to it.
ItemsThe first item’s name and “+4 more”. The full list is in the row expansion.
TotalThe offer’s current total.
FMVThe items’ combined fair market value.
PA #The offer’s PA number, when it has one.
Offer statusThe offer’s current status, with the signature state shown as today.
SentWhen the offer was sent, and when it was last acted on.
Account managerThe facility’s account manager, or “Several” if the items have different ones.
  1. G1Row expansion: each item with its asset, inventory ID, category, quantity and FMV — the same cells as the Individual tab’s asset columns.expansion
  2. G2Row actions act on the whole offer: open the offer thread to accept, counter or reject, as each role may today; view or resend the PA; upload an offline PA (admins); view the order once it has sold.actions
  3. G3Filters: search, groups, regions, facilities and categories match an offer when any of its items matches; plus status and vendor. Paging, filtering and sorting run in SQL — by sent date, last action, total, item count or status.filters
  4. G4Summary line: offers, awaiting response and total offer value, each offer counted once.summary

Tab counts and tilesboth tabs

APIbackendApi · primary role

  1. A1offerType on today’s two list endpoints — GET /vendor-offer/my-offers and GET /marketplace/sell-to-capexpert — with individual as the default, so a caller that sends nothing gets tab 1. It limits the rows, counts, status and summary to offers with an item_count of 1. The category facet endpoints take the same parameter, so each tab’s category filter counts its own offers.change
  2. A2offerType on GET /vendor-offer/:marketplaceId, the vendor offers on one listing. The default stays every offer, with group offers marked; the Individual tab’s expansion asks for individual.change
  3. A3New GET /vendor-offer/group-offers for admins, management groups and facilities — the guard the listing’s offers route already uses. A facility sees group offers on its own listings, a management group its facilities’, an admin all of them. It returns the rows above, paged, filtered and sorted in SQL, with the summary and both tab counts.Declared before /:marketplaceId, so group-offers is not read as a listing id.new
  4. A4New GET /vendor-offer/group-offers/:id/items for the row expansion, under the same access check.new

Front endcapExpertApp

  1. F1The tab bar: app-tabs in its segmented style, above the filters on both pages — Individual Offers and Group Offers, each with its count. The chosen tab is kept in the URL as ?view=group, so refresh, back and shared links keep it, and a notification or DocuSign link to a group offer opens the Group tab on that offer.new
  2. F2Tab 1 is today’s table on each page. It asks for offerType=individual and shows the “In a group offer” badge.change
  3. F3Tab 2 is one new standalone GroupOffersTableComponent, used by both pages, built on cs-data-table with row detail for the items. Its actions open the offer thread modal for the whole offer; the role decides which actions show, as today’s row menus do.new
  4. F4The filter bar is shared by both tabs. On Group Offers, search, groups, regions, facilities and categories apply to any item in an offer.change
  5. F5Regenerate the swagger client for the new endpoints and parameters, and restart the front end.step

Proofbefore the tabs are called done

  1. P1A listing with one individual offer and one group offer appears on both tabs: tab 1 counts only the individual offer and shows the badge, tab 2 shows the group offer once.rows
  2. P2A listing with only group offers is not on tab 1.rows
  3. P3Each tab’s badge matches that list’s total under every filter, and totals and “awaiting response” count each group offer once.counts
  4. P4A facility sees only group offers on its own listings, a management group only its facilities’, an admin all of them.access
  5. P5A call to my-offers or sell-to-capexpert without offerType returns exactly tab 1.contract