MedBridge Sales Ops — Quote, Reconciliation & Account Decision Packages
Environment entrypoint
The MedBridge Sales Ops API is always accessed through the task environment base URL.
When the task text mentions API_BASE_URL, BASE_URL, localhost, 127.0.0.1, or
env/setup.sh, substitute the remote URL declared in the runner's environment access
configuration. Do not start a local env or read an env/ source directory.
Task taxonomy
MedBridge tasks fall into three patterns. Identify which one applies before calling
any API endpoint.
Pattern A — Quote decision package (EXW + freight comparison)
Recognised by: a quote ID like Q-TR-*, a product code, a confirmed quantity,
and a request for "EXW pricing" plus "freight options" or "transport comparison."
API endpoints to call (in order):
- Customer record — resolve the customer ID from the prompt or quote context.
- Quote / opportunity — fetch the quote by ID; confirm
quote_date, product,
quantity, and quote basis (EXW).
- Product catalog — get the product's unit price and tier (volume bands),
lead time, and shelf life.
- Freight records — fetch all freight options (
AIR, SEA, ROAD) for the
product or product family.
- Policy records — fetch the customer's account policy (payment terms, NGO
status, freight reconfirmation flag).
Calculation rules:
| Field |
Formula |
unit_price_usd |
From the catalog tier whose min_quantity ≤ confirmed_quantity ≤ max_quantity |
exw_total_usd |
unit_price_usd × confirmed_quantity |
grand_total_usd (per freight option) |
exw_total_usd + freight_cost_usd |
Freight validity check:
- Compare
valid_until against quote_date.
- If
valid_until < quote_date → validity_status: "STALE", source_is_stale: true.
- If
valid_until ≥ quote_date → validity_status: "VALID", source_is_stale: false.
Route risk flags:
customs_border_risk: "LOW", "MEDIUM", or "HIGH" — read from the freight
record's risk assessment.
risk_flag: "NONE" when low, "MEDIUM_BORDER_RISK" when medium, or a
descriptive flag from the API payload.
- A road freight option whose
valid_until is before quote_date and has
HIGH border risk must trigger road_quote_invalid_or_stale: true and a
human-readable freight_warning.
Recommended transport mode:
- Default to
"SEA" when it is valid (not stale) and has low risk — it offers the
best cost/safety balance.
- If SEA is stale or high-risk, fall back to
"AIR" if valid.
- Never recommend a stale or high-risk option.
Freight reconfirmation:
freight_reconfirmation_required: true whenever any freight option is stale
or has risk level MEDIUM or above.
Payment terms:
- Recurring NGO accounts →
"NET_30_AFTER_PO".
- New NGO / first-time accounts →
"PREPAY_100".
- Read the actual term string from the customer policy record — do not hardcode.
Client warnings (Pattern A variant — see train 004):
- When the output template includes a
client_warnings block, include:
road_quote_invalid_or_stale (boolean).
freight_warning (human-readable sentence naming the stale freight ID,
its expiry date, and risk level).
policy_terms repeating quote_basis, payment_terms, and
freight_reconfirmation_required.
Pattern B — EXW-only module / RFQ quote (no freight)
Recognised by: an RFQ ID like RFQ-TR-*, module product codes (e.g.
IEHK-*), an explicit instruction to quote EXW only with freight excluded,
and often a "new NGO account."
API endpoints to call (in order):
- Customer record — confirm the customer exists and is classified correctly
(new vs recurring NGO).
- RFQ / quote record — fetch by RFQ ID; get the requested modules and
their quantities.
- Product catalog — for each module, retrieve
article_number, unit_price,
lead_time_days, and shelf_life_months.
- Policy records — get payment terms, offer validity, and WHO documentation
requirements.
Critical rule — module level only:
- Even if the API returns sub-components or BOM details for a module, quote at
the module level as requested by the customer. Do not explode modules into
their components in the line items.
Calculation rules:
| Field |
Formula |
line_total |
unit_price × quantity |
grand_total |
sum of all line_item.line_total |
Fixed controls for Pattern B:
currency: always "USD".
quote_basis: "EXW_ONLY" (not "EXW" — the _ONLY suffix is significant).
freight_excluded: true.
payment_terms: "PREPAY_100" for new NGO accounts.
offer_validity_days: 30 (standard for new accounts).
who_documentation_required: true for NGO/health-sector accounts.
Pattern C — Account / engagement reconciliation
Recognised by: an opportunity ID like OPP-TR-*, a request to "reconcile"
or verify milestone invoices, payment state, revenue recognition, and often a
linked event/voucher.
API endpoints to call (in order):
- CRM opportunity — fetch by
OPP-TR-* ID; confirm stage (WON), won
amount, and linked customer.
- Customer record — verify customer name, ID, and primary contact.
- Milestone invoices — fetch all milestones for the opportunity (typically
MS1, MS2, MS3).
- Payments / receivables — for each milestone, get payment state, amount
paid, amount unpaid, and due date.
- Revenue recognition journal — check which paid milestones have a
corresponding revenue recognition entry.
- Event / voucher — fetch the linked event by ID, confirm status, and
retrieve the attached voucher details.
Reconciliation checks:
Opportunity total vs milestone sum:
phase_total_amount = sum of all milestone.amount
opportunity_matches_phase_total = (won_amount == phase_total_amount)
Outstanding balance:
outstanding_balance = sum of all milestone.amount_unpaid
- Also verify:
won_amount - total_paid_amount == outstanding_balance
Revenue recognition by milestone:
| Milestone state |
Recognition status |
PAID + journal entry exists |
"RECOGNIZED" |
PAID + journal entry missing |
"MISSING_REVENUE_JOURNAL" |
UNPAID |
"NOT_REQUIRED_UNPAID" |
Overall recognition status:
- If all PAID milestones are RECOGNIZED →
"COMPLETE_FOR_PAID_MILESTONES".
- If any PAID milestone is MISSING →
"MISSING_FOR_PAID_MILESTONES".
Invoice state vs payment state — important distinction:
invoice_state reflects whether an invoice was issued ("PAID" / "OPEN" /
"VOID" / "UNKNOWN"). An invoice can be "OPEN" (issued but not yet settled)
while the payment is still processing.
payment_state reflects actual cash received ("PAID" / "PARTIAL" /
"UNPAID" / "UNKNOWN").
- These are independent dimensions — do not conflate them.
Follow-up task generation:
| Condition |
Task |
Any milestone is UNPAID with a future due_date |
COLLECTION → MONITOR_UNPAID_NOT_DUE (monitor, don't collect yet) |
Any milestone is UNPAID with a past due_date |
COLLECTION → COLLECT_UNPAID_MILESTONE (active collection) |
| Event is SCHEDULED or ACTIVE |
EVENT_INVITATION → SEND_EVENT_INVITATION (due ~3 weeks before event) |
Accounting journal entries (Pattern C variant — train 005):
- When a PAID milestone lacks a revenue recognition entry, generate:
debit_account: "DEFERRED_REVENUE"
credit_account: "IMPLEMENTATION_SERVICES_REVENUE"
owner_queue: "ACCOUNTING"
- When all paid milestones ARE recognized →
primary_accounting_action: "VERIFY_REVENUE_ONLY".
Due-date logic for follow-up tasks:
- Collection tasks: use the milestone's
due_date.
- Event invitation tasks: use 21 days before the event date (rounded to the
nearest sensible business day; the examples show exact dates — prefer the date
the API or calculation yields).
Cross-cutting conventions
Money
- All monetary values are in USD with two decimal places (cents).
- Use
float / number type in JSON, not strings.
- Nullable money fields use
null (not 0.0 and not "N/A").
Dates
- All dates are ISO 8601
YYYY-MM-DD strings.
- Nullable date fields use
null (not empty string, not "0000-00-00").
quote_date is the business date the customer confirmed — treat it as "today"
for validity comparisons.
IDs
- Use the exact record IDs returned by the API — do not synthesise, truncate,
or guess IDs.
- Quote IDs:
Q-TR-*
- RFQ IDs:
RFQ-TR-*
- Opportunity IDs:
OPP-TR-*
- Customer IDs:
CUST-*
- Freight IDs:
FR-*-AIR, FR-*-SEA, FR-*-ROAD
- Event IDs:
EVT-*-*
- Voucher codes: as returned by the event/voucher endpoint.
Enums — use exact controlled values
- The answer template declares the permitted enum values in comments
(e.g.
"enum: WON | OPEN | LOST"). Match them exactly, including case.
- Do not invent new status values. If the API returns a status that doesn't
map cleanly to an enum slot, pick the closest match from the template.
Output format
- Return only valid JSON matching the
input/payloads/answer_template.json
structure.
- No markdown fences, no explanatory prose, no trailing text.
- Fill every field in the template — no field left as a placeholder.
Common pitfalls
Wrong tier selected for volume pricing. A product at 1000 units may fall
into the 900–1199 band, not the 500–899 band or the 1200+ band. Always check
min_quantity ≤ confirmed_quantity ≤ max_quantity.
Confusing EXW with EXW_ONLY. EXW means "pricing is EXW but freight
will be compared." EXW_ONLY means "no freight at all — do not fetch or
include freight records."
Stale freight not flagged. If valid_until < quote_date, the freight
option must be marked stale/invalid. This is the single most common omission.
Forgetting to sum milestone amounts. phase_total_amount and
outstanding_balance must be computed by summing the individual milestone
fields — they are not a separate API field.
Invoice state vs payment state confusion. A milestone can have
invoice_state: "PAID" (the invoice was issued and marked paid) but
payment_state: "PAID" (cash received) — these should normally agree for
settled milestones. When they disagree, reflect both accurately.
Revenue recognition for unpaid milestones. An UNPAID milestone never
requires revenue recognition — its status is always "NOT_REQUIRED_UNPAID",
never "MISSING_REVENUE_JOURNAL".
Contact linking. The contact named in the prompt must appear in every
follow-up task, the account_status/engagement_reconciliation block, and any
invite or collection task. Verify the contact is linked to the correct
customer and opportunity in the API response.
New NGO vs recurring NGO payment terms. New/first-time NGO accounts get
PREPAY_100. Recurring NGO accounts with established history get
NET_30_AFTER_PO. Verify by checking the customer's account age or policy
record — don't assume.
Freight reconfirmation flag. Set to true when ANY freight option is
stale OR has medium-or-higher risk. Even one bad option triggers this — it
doesn't require all options to be problematic.
Event invitation lead time. The invitation task's due_date should
allow reasonable lead time before the event. The train examples show ~3
weeks before the event date — apply the same logic but use the actual date
the API or calculation produces.
API call order (all patterns)
Always follow this dependency order — later calls often need IDs from earlier
responses:
1. Customer / account record
2. Quote / RFQ / Opportunity record
3. Product catalog (for quote tasks) or Milestone invoices (for reconciliation tasks)
4. Freight records (Pattern A only)
5. Policy / payment terms
6. Event / voucher (Pattern C only)
7. Revenue recognition journal (Pattern C only)
If an upstream call fails or returns no record, do not proceed to dependent
calls — report the gap in the output (use null for nullable fields, or the
closest error-indicating enum value).
1---2name: fewshot-attempt-01-293description: MedBridge Sales Ops — Quote, Reconciliation & Account Decision Packages4---5# MedBridge Sales Ops — Quote, Reconciliation & Account Decision Packages67## Environment entrypoint89The MedBridge Sales Ops API is always accessed through the task environment base URL.10When the task text mentions `API_BASE_URL`, `BASE_URL`, `localhost`, `127.0.0.1`, or11`env/setup.sh`, substitute the remote URL declared in the runner's environment access12configuration. Do **not** start a local env or read an `env/` source directory.1314---1516## Task taxonomy1718MedBridge tasks fall into three patterns. Identify which one applies before calling19any API endpoint.2021### Pattern A — Quote decision package (EXW + freight comparison)2223**Recognised by:** a quote ID like `Q-TR-*`, a product code, a confirmed quantity,24and a request for "EXW pricing" plus "freight options" or "transport comparison."2526**API endpoints to call (in order):**27281. **Customer record** — resolve the customer ID from the prompt or quote context.292. **Quote / opportunity** — fetch the quote by ID; confirm `quote_date`, product,30 quantity, and quote basis (`EXW`).313. **Product catalog** — get the product's unit price and tier (volume bands),32 lead time, and shelf life.334. **Freight records** — fetch all freight options (`AIR`, `SEA`, `ROAD`) for the34 product or product family.355. **Policy records** — fetch the customer's account policy (payment terms, NGO36 status, freight reconfirmation flag).3738**Calculation rules:**3940| Field | Formula |41|---|---|42| `unit_price_usd` | From the catalog tier whose `min_quantity ≤ confirmed_quantity ≤ max_quantity` |43| `exw_total_usd` | `unit_price_usd × confirmed_quantity` |44| `grand_total_usd` (per freight option) | `exw_total_usd + freight_cost_usd` |4546**Freight validity check:**47- Compare `valid_until` against `quote_date`.48- If `valid_until < quote_date` → `validity_status: "STALE"`, `source_is_stale: true`.49- If `valid_until ≥ quote_date` → `validity_status: "VALID"`, `source_is_stale: false`.5051**Route risk flags:**52- `customs_border_risk`: `"LOW"`, `"MEDIUM"`, or `"HIGH"` — read from the freight53 record's risk assessment.54- `risk_flag`: `"NONE"` when low, `"MEDIUM_BORDER_RISK"` when medium, or a55 descriptive flag from the API payload.56- A road freight option whose `valid_until` is before `quote_date` **and** has57 `HIGH` border risk must trigger `road_quote_invalid_or_stale: true` and a58 human-readable `freight_warning`.5960**Recommended transport mode:**61- Default to `"SEA"` when it is valid (not stale) and has low risk — it offers the62 best cost/safety balance.63- If SEA is stale or high-risk, fall back to `"AIR"` if valid.64- Never recommend a stale or high-risk option.6566**Freight reconfirmation:**67- `freight_reconfirmation_required: true` whenever **any** freight option is stale68 or has risk level `MEDIUM` or above.6970**Payment terms:**71- Recurring NGO accounts → `"NET_30_AFTER_PO"`.72- New NGO / first-time accounts → `"PREPAY_100"`.73- Read the actual term string from the customer policy record — do not hardcode.7475**Client warnings (Pattern A variant — see train 004):**76- When the output template includes a `client_warnings` block, include:77 - `road_quote_invalid_or_stale` (boolean).78 - `freight_warning` (human-readable sentence naming the stale freight ID,79 its expiry date, and risk level).80 - `policy_terms` repeating `quote_basis`, `payment_terms`, and81 `freight_reconfirmation_required`.8283---8485### Pattern B — EXW-only module / RFQ quote (no freight)8687**Recognised by:** an RFQ ID like `RFQ-TR-*`, module product codes (e.g.88`IEHK-*`), an explicit instruction to quote EXW only with freight excluded,89and often a "new NGO account."9091**API endpoints to call (in order):**92931. **Customer record** — confirm the customer exists and is classified correctly94 (new vs recurring NGO).952. **RFQ / quote record** — fetch by RFQ ID; get the requested modules and96 their quantities.973. **Product catalog** — for each module, retrieve `article_number`, `unit_price`,98 `lead_time_days`, and `shelf_life_months`.994. **Policy records** — get payment terms, offer validity, and WHO documentation100 requirements.101102**Critical rule — module level only:**103- Even if the API returns sub-components or BOM details for a module, quote at104 the **module level** as requested by the customer. Do not explode modules into105 their components in the line items.106107**Calculation rules:**108109| Field | Formula |110|---|---|111| `line_total` | `unit_price × quantity` |112| `grand_total` | `sum of all line_item.line_total` |113114**Fixed controls for Pattern B:**115- `currency`: always `"USD"`.116- `quote_basis`: `"EXW_ONLY"` (not `"EXW"` — the `_ONLY` suffix is significant).117- `freight_excluded`: `true`.118- `payment_terms`: `"PREPAY_100"` for new NGO accounts.119- `offer_validity_days`: `30` (standard for new accounts).120- `who_documentation_required`: `true` for NGO/health-sector accounts.121122---123124### Pattern C — Account / engagement reconciliation125126**Recognised by:** an opportunity ID like `OPP-TR-*`, a request to "reconcile"127or verify milestone invoices, payment state, revenue recognition, and often a128linked event/voucher.129130**API endpoints to call (in order):**1311321. **CRM opportunity** — fetch by `OPP-TR-*` ID; confirm stage (`WON`), won133 amount, and linked customer.1342. **Customer record** — verify customer name, ID, and primary contact.1353. **Milestone invoices** — fetch all milestones for the opportunity (typically136 `MS1`, `MS2`, `MS3`).1374. **Payments / receivables** — for each milestone, get payment state, amount138 paid, amount unpaid, and due date.1395. **Revenue recognition journal** — check which paid milestones have a140 corresponding revenue recognition entry.1416. **Event / voucher** — fetch the linked event by ID, confirm status, and142 retrieve the attached voucher details.143144**Reconciliation checks:**1451461. **Opportunity total vs milestone sum:**147 - `phase_total_amount = sum of all milestone.amount`148 - `opportunity_matches_phase_total = (won_amount == phase_total_amount)`1491502. **Outstanding balance:**151 - `outstanding_balance = sum of all milestone.amount_unpaid`152 - Also verify: `won_amount - total_paid_amount == outstanding_balance`1531543. **Revenue recognition by milestone:**155156 | Milestone state | Recognition status |157 |---|---|158 | `PAID` + journal entry exists | `"RECOGNIZED"` |159 | `PAID` + journal entry missing | `"MISSING_REVENUE_JOURNAL"` |160 | `UNPAID` | `"NOT_REQUIRED_UNPAID"` |1611624. **Overall recognition status:**163 - If **all** PAID milestones are RECOGNIZED → `"COMPLETE_FOR_PAID_MILESTONES"`.164 - If **any** PAID milestone is MISSING → `"MISSING_FOR_PAID_MILESTONES"`.165166**Invoice state vs payment state — important distinction:**167- `invoice_state` reflects whether an invoice was issued (`"PAID"` / `"OPEN"` /168 `"VOID"` / `"UNKNOWN"`). An invoice can be `"OPEN"` (issued but not yet settled)169 while the payment is still processing.170- `payment_state` reflects actual cash received (`"PAID"` / `"PARTIAL"` /171 `"UNPAID"` / `"UNKNOWN"`).172- These are independent dimensions — do not conflate them.173174**Follow-up task generation:**175176| Condition | Task |177|---|---|178| Any milestone is UNPAID with a future `due_date` | `COLLECTION` → `MONITOR_UNPAID_NOT_DUE` (monitor, don't collect yet) |179| Any milestone is UNPAID with a past `due_date` | `COLLECTION` → `COLLECT_UNPAID_MILESTONE` (active collection) |180| Event is SCHEDULED or ACTIVE | `EVENT_INVITATION` → `SEND_EVENT_INVITATION` (due ~3 weeks before event) |181182**Accounting journal entries (Pattern C variant — train 005):**183- When a PAID milestone lacks a revenue recognition entry, generate:184 - `debit_account: "DEFERRED_REVENUE"`185 - `credit_account: "IMPLEMENTATION_SERVICES_REVENUE"`186 - `owner_queue: "ACCOUNTING"`187- When all paid milestones ARE recognized → `primary_accounting_action: "VERIFY_REVENUE_ONLY"`.188189**Due-date logic for follow-up tasks:**190- Collection tasks: use the milestone's `due_date`.191- Event invitation tasks: use **21 days before** the event date (rounded to the192 nearest sensible business day; the examples show exact dates — prefer the date193 the API or calculation yields).194195---196197## Cross-cutting conventions198199### Money200- All monetary values are in **USD** with **two decimal places** (cents).201- Use `float` / `number` type in JSON, not strings.202- Nullable money fields use `null` (not `0.0` and not `"N/A"`).203204### Dates205- All dates are **ISO 8601** `YYYY-MM-DD` strings.206- Nullable date fields use `null` (not empty string, not `"0000-00-00"`).207- `quote_date` is the business date the customer confirmed — treat it as "today"208 for validity comparisons.209210### IDs211- Use the **exact record IDs** returned by the API — do not synthesise, truncate,212 or guess IDs.213- Quote IDs: `Q-TR-*`214- RFQ IDs: `RFQ-TR-*`215- Opportunity IDs: `OPP-TR-*`216- Customer IDs: `CUST-*`217- Freight IDs: `FR-*-AIR`, `FR-*-SEA`, `FR-*-ROAD`218- Event IDs: `EVT-*-*`219- Voucher codes: as returned by the event/voucher endpoint.220221### Enums — use exact controlled values222- The answer template declares the permitted enum values in comments223 (e.g. `"enum: WON | OPEN | LOST"`). Match them **exactly**, including case.224- Do not invent new status values. If the API returns a status that doesn't225 map cleanly to an enum slot, pick the closest match from the template.226227### Output format228- Return **only** valid JSON matching the `input/payloads/answer_template.json`229 structure.230- No markdown fences, no explanatory prose, no trailing text.231- Fill **every** field in the template — no field left as a placeholder.232233---234235## Common pitfalls2362371. **Wrong tier selected for volume pricing.** A product at 1000 units may fall238 into the 900–1199 band, not the 500–899 band or the 1200+ band. Always check239 `min_quantity ≤ confirmed_quantity ≤ max_quantity`.2402412. **Confusing `EXW` with `EXW_ONLY`.** `EXW` means "pricing is EXW but freight242 will be compared." `EXW_ONLY` means "no freight at all — do not fetch or243 include freight records."2442453. **Stale freight not flagged.** If `valid_until < quote_date`, the freight246 option must be marked stale/invalid. This is the single most common omission.2472484. **Forgetting to sum milestone amounts.** `phase_total_amount` and249 `outstanding_balance` must be computed by summing the individual milestone250 fields — they are not a separate API field.2512525. **Invoice state vs payment state confusion.** A milestone can have253 `invoice_state: "PAID"` (the invoice was issued and marked paid) but254 `payment_state: "PAID"` (cash received) — these should normally agree for255 settled milestones. When they disagree, reflect both accurately.2562576. **Revenue recognition for unpaid milestones.** An UNPAID milestone never258 requires revenue recognition — its status is always `"NOT_REQUIRED_UNPAID"`,259 never `"MISSING_REVENUE_JOURNAL"`.2602617. **Contact linking.** The contact named in the prompt must appear in every262 follow-up task, the account_status/engagement_reconciliation block, and any263 invite or collection task. Verify the contact is linked to the correct264 customer and opportunity in the API response.2652668. **New NGO vs recurring NGO payment terms.** New/first-time NGO accounts get267 `PREPAY_100`. Recurring NGO accounts with established history get268 `NET_30_AFTER_PO`. Verify by checking the customer's account age or policy269 record — don't assume.2702719. **Freight reconfirmation flag.** Set to `true` when ANY freight option is272 stale OR has medium-or-higher risk. Even one bad option triggers this — it273 doesn't require all options to be problematic.27427510. **Event invitation lead time.** The invitation task's `due_date` should276 allow reasonable lead time before the event. The train examples show ~3277 weeks before the event date — apply the same logic but use the actual date278 the API or calculation produces.279280---281282## API call order (all patterns)283284Always follow this dependency order — later calls often need IDs from earlier285responses:286287```2881. Customer / account record2892. Quote / RFQ / Opportunity record2903. Product catalog (for quote tasks) or Milestone invoices (for reconciliation tasks)2914. Freight records (Pattern A only)2925. Policy / payment terms2936. Event / voucher (Pattern C only)2947. Revenue recognition journal (Pattern C only)295```296297If an upstream call fails or returns no record, do not proceed to dependent298calls — report the gap in the output (use `null` for nullable fields, or the299closest error-indicating enum value).