# Walmart Price Calculation

**1.** All calculations below are for Walmart Max Price. The difference between Max Price and Min Price calculation is described in p12.

**1a. Implementation storage (this project)** — keeps the math below unchanged; only clarifies **where inputs and outputs live** in the database:

* **Do not** extend `reprice_settings.data` for Walmart min/max algorithm configuration. Use a dedicated store-level table **`min_max_settings`** (`walmart_key_id`, optional `item_id` for overrides): default ref fee, MAP ignore flag, misc fee markup (**8.1**), border optimization knobs (**9.6** / **9.7**), WFS reduce-fee rule (**9.3**), effective min/max policy, etc.
* **Do not** add new columns on **`items`** for algorithm transparency. Use a 1:1 table **`items_extra`** keyed by `item_id` for per-SKU fields such as: `site_cost`, base `misc_fee`, `map_price`, `enforce_map_price`, `sku_map_on_walmart`, optional margin overrides (**6.1** / **6.3**), user vs calculated min/max mirrors, `value_difference` (**7.2.2.1**), `wfs_qty_zero_date` (ATS = 0 tracking for **7.2.1**), and metadata for which value won for effective min/max. Migration should enforce **`UNIQUE(item_id)`** on `items_extra`.
* **Reconciliation snapshots** for **7.2.2.1** are persisted in **`reconciliation_reports`** (at minimum: `walmart_key_id`, `walmart_item_id`, `fulfillment_fee`, `report_date`) so runtime can compare item report weight update vs reconciliation date. Ingestion from the Walmart Reconciliation report is a separate pipeline.
* **Calculation run history** — each `MinMaxService::recalculateForItem` persistence pass appends **`min_max_calculation_history`** (`item_id`, `walmart_key_id`, `input_snapshot_hash`, `is_wfs`, JSON **`explain`**): snapshots of min/max intermediate fields, ordered **`rules_applied`** codes keyed to sections in this doc (e.g. `6.2.6.2`, `7.2.2.1`, `9.4.2`, `9.6`, `11`), effective min/max + sources, and optional **`section_12_reconcile`** before/after when the §12 reconciler adjusts the pair.
* **Effective** min/max used by the existing repricer stay on **`items.min_price`**, **`items.max_price`** (and WFS variants if used). A resolver chooses between user/import vs calculated values using policy from `min_max_settings` and writes the winner into `items.*` plus optional source flags on `items_extra`.

**2.** There is a file that the user uploads with many values, I will refer to it further as data from p2.

**3.** There is an overwrite setting in UI (or p2). If it is set, we take this price and do not calculate.

* **3.1.** Also, there is enforce_map_price from p2: if p3 is not used, and enforce_map_price value is set (p2), and enforce_map_price = True (p2), then price cannot be lower than map_price. In the DB model, treat **`map_price`**, **`enforce_map_price`**, and **`sku_map_on_walmart`** as **per-SKU** fields (p2 / `items_extra`), not as store-wide settings. Store-wide **`ignore_map_on_walmart`** lives in **`min_max_settings`** (see **11**).

**4.** walmart max price = (site_cost + walmart_max_price_margin + walmart_shipping_cost + misc_fee)

**5.** **site_cost** is **landed cost / accounting cost** from p2 (or synced into **`items_extra.site_cost`**). It must **not** be confused with **`items.current_price`** or listing price.

**6.** walmart_max_price_margin:

* **6.1.** margin can be overwritten same as price in p3, first priority - p2, second - settings, third - p6.2
* **6.2.** walmart_max_price_margin (API):
  * **6.2.1.** Source:
    * Calculated via Margin.get_max_margin()
  * **6.2.2.** Marketplace normalization:
    * if marketplace_country is in EU → converted to UK
    * default → US
  * **6.2.3.** Warehouse rule priority:
    * *(Implementation note: this branch may be deferred in the Walmart min/max rollout; when disabled, fall through to **6.2.4** / **6.2.5** / **6.2.6**.)*
    * if warehouse_match_rule exists AND has margin:
      * warehouse_match_rule logic: user uploads a file with SKU warehouse quantities; only warehouses with qty > 0 are used to form a set; rules are configured in UI; for each SKU a rule is selected where the full warehouse set matches and vendor matches; the first matching rule is applied
      * use warehouse margin:
        * if type = PERCENT: margin = site_cost x margin_percent
        * if type = FIXED: margin = fixed value (from settings)
      * apply margin_not_lower if defined
    * in the end of 6.2.3 we get warehouse_match_rule_margin, has more priority than 6.2.4, if priority of 6.2.4 is not set in settings
  * **6.2.4.** Custom quantity (inventory age) rules:
    * applied if:
      * inventory age rules exist AND inventory_age_item is present (huge report-based logic which stores data of different quantities: afn_fulfillable_quantity, afn_reserved_quantity, afn_total_quantity, active_quantity, reserved_customerorders, reserved_fc_transfers, reserved_fc_processing, event_detail_custom, event_detail_30, event_detail_receipt_30, event_detail_60, event_detail_90, event_detail_120, quantity_custom, quantity_30, quantity_60, quantity_90, quantity_120; quantity_30 = quantity for last 30-60 days)
      * custom quantity rules are configured (example: if quantity > X, set max and min margin to value from settings)
    * select rule based on:
      * item age (30 / 60 / 90 / 120+ days)
      * category match
      * inactivity rules (optional)
    * if rule found:
      * margin depends on rule type:
        * PERCENT -> site_cost x %
        * FIXED -> fixed value
        * MULTIPLIER -> max_margin x min_margin
      * apply margin_not_lower
      * mark age_rule_condition = True
    * in the end of 6.2.4 we get custom quantity margin, has more priority than 6.2.5
  * **6.2.5.** Marketplace rules (main logic):
    * select applicable rule based on:
      * site_cost range (item_cost_above) - rule is applied if site_cost is above item_cost_above from settings
      * item type (can be set from UI or taken from reports): Regular, FBM, Hazmat, Oversize
    * additional filters:
      * sales-based conditions (30-60 / 60-90 / 90-120 days)
      * can skip rule if sales % is above threshold:
        * sales_percent = sales_quantity / avail_qty x 100
        * sales_quantity = sales last 7 days, avail_qty = inventory_age_item.active_quantity
    * if rule selected:
      * determine margin:
        * PERCENT -> site_cost x %
        * FIXED -> fixed value
        * MULTIPLIER -> max_margin x calculated_min_margin
      * apply margin_not_lower
    * in the end of 6.2.5 we get margin, has more priority than 6.2.6
  * **6.2.6.** Fallback to margin settings:
    * if no rules applied, use InventoryHealth settings:
      * **6.2.6.1.** no settings or invalid site_cost -> return margin_not_lower OR 0
      * **6.2.6.2.** PERCENT: margin = site_cost x max_margin_percent, apply margin_not_lower
      * **6.2.6.3.** FIXED: margin = max_margin_value; if count_as_usd -> apply currency conversion; apply margin_not_lower
      * **6.2.6.4.** MULTIPLIER: min_margin = calculated via min margin logic; margin = multiplier x min_margin; apply margin_not_lower
  * **6.2.7.** Final result:
    * margin is float, margin_not_lower enforced
    * returns: margin value, condition (optional, for logs/debug)
* **6.3.** walmart_min_price_margin:
  * same source priority as max margin (p6.1):
    * if walmart_min_margin from input file -> margin = walmart_min_margin % x site_cost, then margin_not_lower enforced
    * elif walmart_min_margin from sku editor -> margin = walmart_min_margin % x site_cost
    * else -> calculated via get_min_margin (same rule priority as p6.2: warehouse rule -> custom quantity rules -> marketplace rules -> fallback to settings), but uses min_margin fields instead of max_margin fields, and MULTIPLIER type is not supported for min margin

**7.** walmart_shipping_cost:

* **7.1.** can be overwritten only from settings
* **7.2.** if item is WFS:
  * **7.2.1.** item is WFS if:
    * can be overwritten same as price in p3
    * data from WFS Inventory Report: item has positive on-hand quantity AND (available-to-sale quantity > 0 OR it has been 0 for less than 7 days in a row)
      * *(Persistence: track “ATS stayed at 0 since …” on **`items_extra.wfs_qty_zero_date`** — if no history, treat the “&lt; 7 days” branch as false per Q/A.)*
    * fulfillment_type = 'Walmart Fulfilled' (from Walmart Item Report)
  * **7.2.2.** data from: recon = Walmart Reconciliation Report, item = Walmart Item Report; priority:
    * **7.2.2.1.** Reconciliation Report + Item Report:
      * cost = get_cost_for_weight(item_report_shipping_weight + 0.25)
        * get_cost_for_weight = table 'Fulfillment fee based on item weight' from <https://marketplace.walmart.com/walmart-fulfillment-services-pricing/>
      * **`reconciliation_fulfillment_fee`** and **`reconciliation_report_date`** come from the persisted reconciliation snapshot (**`reconciliation_reports`**) / ingestion, aligned with **Item Report** dates for comparison.
      * if item_report_shipping_weight_updated > reconciliation_report_date:
        * cost += stored **value_difference** (if exists) — stored on **`items_extra.value_difference`**
      * else:
        * if **(reconciliation_fulfillment_fee - cost) == 0.5** exactly: store **value_difference = reconciliation_fulfillment_fee - item_report_ship_cost** on **`items_extra`** (only this exact delta is persisted; **0.49** or **0.51** are **not** treated as **0.5** and are not stored)
      * *(Q/A: rounding is to 2 decimals; near-miss values do not collapse to 0.5.)*
    * **7.2.2.2.** Reconciliation Report fallback (if cost is not calculated above):
      * cost = reconciliation_fulfillment_fee
    * **7.2.2.3.** Item Report fallback:
      * cost = get_cost_for_weight(item_report_shipping_weight + 0.25)
    * **7.2.2.4.** Amazon dimensions fallback (all dims from Amazon):
      * dimensional_weight = (length x height x width) / 139
      * cost = get_cost_for_weight(0.25 + max(shipping_weight, dimensional_weight))
      * **7.2.2.4.1.** calculate_shipping_weight:
        * input: unit_weight, dimensional_weight, size_tier, low_price_fba_fee_condition
        * if size_tier is LARGE_STANDARD, LARGE_BULKY, or EXTRA_LARGE (or low_price_fba_fee_condition is True and size_tier is LARGE_STANDARD), AND dimensional_weight > unit_weight:
          * shipping_weight = dimensional_weight
        * else:
          * shipping_weight = unit_weight
        * rounding:
          * if shipping_weight < 1 lb: round up to nearest 1/16 lb (ceil(shipping_weight x 16) / 16)
          * else: round up to nearest whole lb (ceil(shipping_weight))
        * returns: shipping_weight
* **7.3.** use local shipping cost for Walmart if:
  * shipping_cost_function is MULTIFULFILLMENT (setting "If qty is 0 everywhere - calculate shipping as MCF"), AND
  * weight_mcf_value (float value from setting "lbs - use MCF rates, even if qty in Local") is set, AND
  * unit_weight < weight_mcf_value (for "under" condition) OR unit_weight > weight_mcf_value (for "above" condition)
    * unit weight priority: amazon_shipping_weight, sc_shipping_weight_lb, default_weight_value (settings)
  * calculation:
    * **7.3.1.** select shipping table: use provided table or fallback to user's default local table; if no table -> return error; table example: value_from = 3.5, value_to = 4, ship_cost = 3 (if 3.5 < item_weight <= 4, ship_cost = 3)
    * **7.3.2.** determine value based on table type:
      * COST -> use site_cost (convert currency if needed)
      * WEIGHT -> use item weight
      * ITEM_VOLUME -> use item volume
      * if required value is missing -> return error
    * **7.3.3.** find matching row: value_from <= value <= value_to; fallback: first row with value_to >= value; if no match -> return error
    * **7.3.4.** calculate shipping cost, apply currency conversion if needed
* **7.4.** use default shipping cost (calculated for all marketplaces, used for Walmart if no other calc) and function:
  * *(Implementation note: SFP (**7.4.1**) and full MCF/lowest-cost branches may be omitted or simplified in the Walmart-only milestone; default flow can reduce to warehouse/local fallbacks that you actually support.)*
  * **7.4.1.** SFP logic:
    * if merchant_shipping_group (p2) is in SFP_REGIONS AND SFP settings not ignored:
      * SFP_REGIONS = ('nationwideprime', 'Nationwide Prime', 'Regional Prime (Ground)', 'Prime template') - regions that ignore shipping cost and set it to a value defined in SFP settings
      * if SFP shipping table exists AND warehouse rule matches: shipping_cost = from warehouse rule using SFP table
      * else if SFP table not set: shipping_cost = SFP flat setting value
      * else: shipping_cost = 0
  * **7.4.2.** lowest shipping cost mode:
    * if lowest_shipping_cost (settings) is enabled:
      * cost_local = local shipping table (same as p7.3)
      * cost_mcf = MCF calculated fee (Multi-Channel Fulfillment fee based on shipping weight, size tier, and season (peak/non-peak depending on date); selects appropriate pricing table, applies weight-based rules and additional peak fees, optionally converts currency; tables are updated twice per year)
      * shipping_cost = min(cost_local, cost_mcf)
  * **7.4.3.** standard priority flow (if lowest_shipping_cost disabled):
    * **7.4.3.1.** SKU editor (settings): if edited_shipping_cost exists -> use it
    * **7.4.3.2.** Warehouse rule:
      * rule matching logic: match by warehouses from qty file (only where qty > 0) and/or vendor_id
      * rule is valid if: warehouses in rule are empty OR equal to warehouses from file, AND vendor_id in rule is empty OR equals item vendor_id
      * first matched rule is used, result is cached per SKU
      * if rule matches:
        * select shipping table from rule (or fallback to provided/default table)
        * determine value based on table type: COST -> site_cost, WEIGHT -> amazon_shipping_weight_lb, ITEM_VOLUME -> item_volume
        * if required value is missing -> return error
        * find matching row: value_from <= value <= value_to
        * if match found: shipping_cost = shipping_cost from row
    * **7.4.3.3.** zero quantity case: if all quantities = 0 (file qty.csv or inventory health from settings):
      * if "qty is 0 -> use MCF" enabled: shipping_cost = MCF
      * else: shipping_cost = local (p7.3)
    * **7.4.3.4.** default warehouse qty = 0: shipping_cost = MCF
    * **7.4.3.5.** weight-based MCF override: if weight_mcf_value is set AND condition matches (under/above): shipping_cost = MCF
    * **7.4.3.6.** fallback: shipping_cost = local; if setting "use CI dims first" enabled: weight = max(unit_weight, dimensional_weight)
  * **7.4.4.** final step: convert currency if needed

**8.** Base **misc_fee** comes from p2 (or **`items_extra.misc_fee`** once synced). It is separate from **8.1**.

* **8.1.** **additional_misc_fee** uses **`min_max_settings`** fields (`misc_fee_markup_fee`, `misc_fee_markup_percent`, enable flag): if shipping_cost <= misc_fee_markup_fee, then additional_misc_fee = ship_cost x misc_fee_markup_percent / 100. This works in all cases except: item is WFS (p7.2), ship_cost edited (p7.1), override turned on (when ship_cost = Shipping Override from p7.4). **additional_misc_fee** is always **added** on top of base **misc_fee** (it does not replace it).

**9.** After walmart max price calc, we use it to calc referral fee, and is it worth to decrease price. From now on, price = walmart max price. Walmart referral fee (ref_fee) and price calculation:

* **9.1.** input:
  * price (walmart max price) without ref_fee
  * default_ref_fee (from settings or 15%)
  * category data (**before_fee**, **after_fee**, **border**) for border logic below:
    * **Source of truth for fee tiers:** Walmart’s published referral fee schedule (contract categories), e.g. [Referral fee schedule for contract categories](https://marketplacelearn.walmart.com/guides/Getting%20started/Onboarding/Referral-fee-schedule-for-contract-categories). Seed or maintain a **lookup config** in the app (table or versioned file) derived from that schedule — do not hardcode in code without an updatable source.
    * **How to attach to an item:** take the item’s category from Walmart **Item / Item On-Request** report fields (e.g. `primary_category_path` / `product_category` on `request_item_reports`), normalize if needed, then resolve **before_fee**, **after_fee**, **border** from the lookup config for that category (and any variant rules such as APPAREL bands in **9.5**).
    * **Example:** border = 10, if price + ref_fee > border, use after_fee, else use before_fee (exact branching is in **9.5** / **9.4**).
  * item_is_wfs (p7.2.1)
  * shipping_cost (p7)
  * margin settings (p6 + settings)
  * wm_price_incentives (optional) (p10)
* **9.2.** price incentives (only if item_is_wfs and turned on in settings):
  * price incentives logic is based on API: <https://developer.walmart.com/us-marketplace/reference/get_v3-price-incentives>
  * p9.2.1 and p9.2.2 are separate from calculation tasks, which launched once per day
    * 9.2.1 from API get items to enroll, get reduced ref_fee, target_price, expiration_date
    * 9.2.2 enroll items saved on p9.2.3 (if turned on in settings, different setting from p9.2)
      * this also includes changing prices (using API) for saved items in p9.2.3, but not sure if it is needed, seems wm changed something and prices for enrolled items are auto changed
    * 9.2.3 calculate test price with reduced ref_fee, if calculated price < target_price, and current_date < expiration_date:
      * on first run: save this data and go to 9.3
      * on second run, and after 9.2.2, use this reduced ref_fee and this calc, and say to user that this calc was used "Price was changed to X activate WM price incentives discount for ref fee to get bef_border_fee% instead of after_border_fee%"
    * else go to 9.4
* **9.3.** there is a rule in settings for all next 9.x points, which applied before calc, but with all rules applied in this calc:
  * "If Walmart Price Below X Reduce Walmart Fulfillment Fee By Y" - if rule is turned on and item_is_wfs, we do additional calc:
    * if (price - ship_cost) < X: take test_price (price - Y), and calculate final_price. If final_price < X, use this calculation, and reduce ship_cost by Y **for messaging only** — the persisted **`walmart_shipping_cost`** used elsewhere (e.g. min price path) **is not mutated**; **test_price** is equivalent to lowering shipped cost by **Y** in the combined sum.
    * else ignore this rule and do regular calc.
* **9.4.** no category or no borders. Means item is not in report or item has certain ref fee, without "if price below X ref fee = Y%, else Z%". If not called from other places ref_fee = default_ref_fee (p9.1):
  * **9.4.1.** base formula:
    * RF_price (price + ref_fee) = price x 100 / (100 - ref_fee)
  * **9.4.2.** first check:
    * if RF_price >= 10:
      * final_price = RF_price
      * ship_cost_increased = False (means we say to user, that ship_cost was not increased, because price >= 10)
  * **9.4.3.** if item_is_wfs and RF_price < 10:
    * price = price + 1
    * ship_cost_increased = True
    * recalc:
      * RF_price = price x 100 / (100 - ref_fee)
    * if RF_price >= 10:
      * final_price = 10
      * changed = True (means we say to user, that price was changed to 10, to avoid adding + 1, as it is more profitable)
    * else:
      * final_price = RF_price
      * changed = False
  * **9.4.4.** fallback (means if no p9.3, no p9.4.2, and no 9.4.3):
    * final_price = price x 100 / (100 - ref_fee)
    * changed = False
    * ship_cost_increased = False
* **9.5.** category with borders:
  * **9.5.1.** walmart_changed_referral_fee (from settings) = OFF:
    * **9.5.1.1.** category = APPAREL (some categories have special borders):
      * if price <= 15 AND price x 100 / (100 - 5) <= 15:
        * ref_fee = 5%
        * -> goes into no_border_wm_ref_fee_calc (p9.4)
      * elif 15 < price <= 20 AND 15 < price x 100 / (100 - 10) <= 20:
        * ref_fee = 10%
        * RF_price = price x 100 / (100 - 10)
        * final_price = RF_price, changed = False, ship_cost_increased = False
      * else (price > 20 or RF_price falls outside previous ranges):
        * ref_fee = 15%
        * RF_price = price x 100 / (100 - 15)
        * final_price = RF_price, changed = False, ship_cost_increased = False
    * **9.5.1.2.** other categories, with border:
      * calculate border_price (max price that still gets before_fee after adding ref_fee):
        * if item is WFS: border_price = border x (100 - before_fee) / 100 - 1
        * non-WFS: border_price = border x (100 - before_fee) / 100
      * if price <= border_price:
        * if WFS and price < 10:
          * price = price + 1
          * ship_cost_increased = True
        * RF_price = price x 100 / (100 - before_fee)
        * final_price = RF_price, ref_fee = before_fee, changed = False
      * else (price > border_price):
        * RF_price = price x 100 / (100 - after_fee)
        * if RF_price > border:
          * final_price = RF_price, ref_fee = after_fee, changed = False
        * else (RF_price still doesn't clear the border - price is in the gap between border_price and border):
          * force final_price = border, ref_fee = before_fee, changed = True
    * **9.5.1.3.** other categories, no border:
      * -> goes into no_border_wm_ref_fee_calc with before_fee (p9.4)
  * **9.5.2.** walmart_changed_referral_fee = ON. This rule logic: Rule determines whether it's worth decreasing the item price in order to get a lower referral fee. This logic applies when a category has a referral fee structure that changes at a price border. For example, below $10 the referral fee might be 15%, and above $10 it could drop to 8%. In such a case, reducing the price from $10.81 to $10.00 could result in a lower fee and potentially higher overall profit.
    * **9.5.2.1.** APPAREL category:
      * if price <= 15 AND price x 100 / (100 - 5) <= 15:
        * ref_fee = 5%
        * -> goes into no_border_wm_ref_fee_calc (p9.4)
      * elif 15 < price <= 20 AND 15 < price x 100 / (100 - 10) <= 20:
        * before_border_fee = 5, border = 15, after_border_fee = 10
        * -> goes into is_it_worth_to_decrease_price (p9.6)
      * else (price > 20 or RF_price falls outside previous ranges):
        * before_border_fee = 10, border = 20, after_border_fee = 15
        * -> goes into is_it_worth_to_decrease_price (p9.6)
    * **9.5.2.2.** other categories, with border:
      * if after_border_fee < before_border_fee (e.g. 15% below $100, 8% above):
        * -> goes into is_it_worth_to_increase_price (p9.7)
      * else (after_border_fee >= before_border_fee, usual case, e.g. 8% below $10, 15% above):
        * -> goes into is_it_worth_to_decrease_price (p9.6)
    * **9.5.2.3.** other categories, no border:
      * -> goes into no_border_wm_ref_fee_calc with before_border_fee (p9.4)
* **9.6.** is_it_worth_to_decrease_price:

  Applies when the fee is lower below the border than above it (e.g. 8% below $10, 15% above). The question is: if the price is slightly above the border, is it worth decreasing it to get the lower fee?
  * 9.6.1. ship_cost_decreased rule - (p9.3)
  * 9.6.2. main calculation:
    * calculate border_price (maximum price that, after adding ref_fee, still stays below the border):
      * if WFS and border = 10: border_price = border x (100 - before_border_fee) / 100 - 1
      * else: border_price = border x (100 - before_border_fee) / 100
    * if price <= border_price:
      * RF_price = price x 100 / (100 - before_border_fee)
      * if RF_price >= 10:
        * final_price = RF_price, ref_fee = before_border_fee, decreased = False, ship_cost_increased = False
      * elif price < 10 and WFS:
        * price = price + 1, ship_cost_increased = True
        * if price x 100 / (100 - before_border_fee) >= 10:
          * final_price = 10, decreased = True
        * else:
          * final_price = price x 100 / (100 - before_border_fee), decreased = False
      * else:
        * final_price = price x 100 / (100 - before_border_fee), decreased = False, ship_cost_increased = False
    * else (price > border_price - price is above the threshold where before_border_fee applies):
      * RF_price = price x 100 / (100 - after_border_fee)
      * calculate coef_value (the upper limit beyond which it's not worth decreasing), taken from settings (example: Lower WM prices to 10 to get 8% ref fee: % of margin or fixed $):
        * if lower_wm and lower_wm_type are set:
          * if type = 'fixed_value' ($): add_to_border = lower_wm
          * if type = percentage (% of margin): add_to_border = margin x lower_wm / 100
          * coef_value = border + add_to_border
        * else: coef_value = inf
      * if RF_price <= coef_value:
        * compare net revenue at border vs at current RF_price:
          * net at border = border - border x before_border_fee / 100
          * net at RF_price = RF_price - RF_price x after_border_fee / 100
        * if net at border > net at RF_price (decreasing price is more profitable) same but in formula type: if (border - border \* before_border_fee / 100) > (rf_price - rf_price \* after_border_fee / 100):
          * decreased = True, final_price = border, changed_price = RF_price (saved for display)
        * else:
          * final_price = RF_price, ref_fee = after_border_fee, decreased = False
      * else (RF_price > coef_value - too far above border, not worth decreasing):
        * final_price = RF_price, ref_fee = after_border_fee, decreased = False
* **9.7.** is_it_worth_to_increase_price:

  Applies when the fee is lower above the border than below it (e.g. 15% below $100, 8% above). The question is: if the price is slightly below the border, is it worth increasing it to get the lower fee?
  * 9.7.1. ship_cost_decreased rule - (p9.3)
  * 9.7.2. main calculation:
    * if price >= border:
      * RF_price = price x 100 / (100 - after_border_fee)
      * final_price = RF_price, ref_fee = after_border_fee, increased = False, ship_cost_increased = False
    * else (price < border):
      * RF_price = price x 100 / (100 - before_border_fee)
      * if RF_price >= 10:
        * final_price = RF_price, ref_fee = before_border_fee, increased = False, ship_cost_increased = False
      * elif price < 10 and WFS:
        * price = price + 1, ship_cost_increased = True
        * if price x 100 / (100 - before_border_fee) >= 10:
          * increased = True, final_price = 10
          * return immediately
      * RF_price = price x 100 / (100 - before_border_fee)
      * calculate coef_value (the upper limit beyond which it's not worth increasing):
        * if lower_wm and lower_wm_type are set:
          * if type = 'fixed_value': dec_border = lower_wm
          * if type = percentage: dec_border = margin x lower_wm / 100
          * coef_value = border + dec_border
        * else: coef_value = inf
      * if border <= RF_price < coef_value:
        * compare net revenue at border vs at RF_price:
          * net at border = border x (1 - before_border_fee / 100)
          * net at RF_price = RF_price x (1 - after_border_fee / 100)
        * if net at border < net at RF_price (increasing price is more profitable):
          * increased = True, final_price = border + 0.01, changed_price = RF_price (saved for display)
        * else:
          * final_price = RF_price, ref_fee = before_border_fee, increased = False
      * else (RF_price < border or RF_price >= coef_value):
        * final_price = RF_price, ref_fee = before_border_fee, increased = False
* **9.8.** output:
  * referral_fee_percent
  * final_price (with referral fee)
  * before_border_fee / after_border_fee
  * changed flag (price adjusted to border)
  * changed_price (original RF price before adjustment)
  * ship_cost_increased (WFS +1 applied)
  * ship_cost_decreased (shipping optimization applied)
  * price_incentives_used

**10.** wm_price_incentives - how it is used in calc described in p9.2. Walmart's Reduced Referral Fee Incentive program encourages sellers to lower their prices to be more competitive. If a seller's item price is above Walmart's target price, Walmart offers a reduced referral fee (e.g. 5% instead of 15%) as an incentive to bring the price down to or below that target. The seller enrolls eligible items, sets the price at or below the target, and receives the lower fee for the duration of the incentive period. Here is how to get data:

* **10.1.** Eligible items:
  * fetches items with status ELIGIBLE from Walmart Price Incentives API (<https://developer.walmart.com/us-marketplace/reference/get_v3-price-incentives>)
  * upserts them into WalmartIncentiveItemEligible, preserving existing enrolled flag
* **10.2.** Enrolled items:
  * fetches items with status ENROLLED from Walmart Price Incentives API (<https://developer.walmart.com/us-marketplace/reference/get_v3-price-incentives>)
  * upserts them into WalmartPriceIncentivesEnrolled
* **10.3.** Enrollment:
  * selects up to 50 eligible items, ordered by expiration_date, where:
    * enrolled = False
    * pricemaker_sent_price is null
    * pricemaker_wm_min, pricemaker_wm_max, incentive_calc_wm_min, incentive_calc_wm_max are not null (this logic explained in 9.2.3, we save calculated price pricemaker_wm_min and max without this logic turned on, and save incentive_calc_wm_min and max with this logic, and then compare max in p10.4)
    * target_price >= incentive_calc_wm_min
    * expiration_date >= now
    * SKU is not already active in WalmartPriceIncentivesEnrolled
    * if any of points not completed - do nothing for item
  * sends batch enrollment feed via INCENTIVE_ENROLLMENT feed API (<https://developer.walmart.com/us-marketplace/reference/reducedreferralfeeincentivesenrollment>)
  * on success marks items as enrolled = True
* **10.4.** Bulk price update:
  * *(Optional / not required for the current min-max implementation — enrollment and calc may proceed without automated bulk price push.)*
  * selects up to 50 items, ordered by sku, where:
    * enrolled = True
    * pricemaker_sent_price is null
    * pricemaker_wm_min, pricemaker_wm_max, incentive_calc_wm_min, incentive_calc_wm_max are not null
    * target_price >= incentive_calc_wm_min
    * expiration_date >= now
    * SKU is not already active in WalmartPriceIncentivesEnrolled
  * sent_price = min(target_price, pricemaker_wm_max)
  * sends PRICE_AND_PROMOTION feed via Walmart Feeds API (<https://developer.walmart.com/us-marketplace/reference/post_v3-feeds>)
  * polls feed status until PROCESSED or ERROR (up to 3 attempts, 60s apart)
  * on success saves pricemaker_sent_price for each SKU
* **10.5.** Cleanup:
  * deletes records from both WalmartPriceIncentivesEnrolled and WalmartIncentiveItemEligible where expiration_date < now - 90 days

**11.** P9 is the final calculation. After it, price can be overwritten by p3.1 if p3 was not used. enforce_map_price for max price:

* Field locations: **`enforce_map_price`**, **`map_price`**, **`sku_map_on_walmart`** — per SKU (p2 / **`items_extra`**). **`ignore_map_on_walmart`** — store-level (**`min_max_settings`**).
* if enforce_map_price = True (p2) AND map_price (p2) is set AND (walmart_api_price is not calculated OR map_price > walmart_api_price) AND (ignore_map_on_walmart (settings) is False OR sku_map_on_walmart is True):
  * walmart_api_price = map_price

**12.** Walmart Min Price and Walmart API Price (Max) follow the same calculation structure, but differ in:

* base price before ref fee:
  * min: site_cost + walmart_min_price_margin + shipping_cost + misc_fee
  * max: site_cost + walmart_max_price_margin + shipping_cost + misc_fee
* purpose: min is the floor price (minimum acceptable), max is the actual price sent to Walmart API
* if max <= min after all calculations:
  * if max is not overwritten: max = min x 1.10
  * if max is overwritten: min = max - 0.01
* price incentives result is saved differently:
  * min price result -> incentive_calc_wm_min
  * max price result -> incentive_calc_wm_max