Bugnik
← All problems

23Price Drop Alert API

Java · Spring BootEasyBug fixSuggested time: 60 min

Price-drop alert REST API (alert limits, CSV price feed, triggers)

Sign in to start

Before you start

You'll get more out of this problem if you're comfortable with:

Language

  • Checked exceptions: try / catch and throws
  • Optional (orElseThrow, filter) instead of get()
  • Records, enums and streams

Libraries and frameworks

  • Spring Boot REST controllers and a @RestControllerAdvice error handler

Build and test tools

  • Reading javac "unreported exception" errors in the Maven output
  • Reading JUnit 5 / MockMvc test failures

Reasoning

  • "At or below" thresholds and money in integer cents

Background

The Shopper Engagement team at a large online retailer lets customers ask to be notified when a product gets cheaper. Customers set a target price; every price feed from merchandising is checked against the active alerts. Since the last release, customers whose target price is hit exactly never hear about it, and asking to cancel an alert that isn't theirs (or doesn't exist) crashes the service instead of answering "not found".

How the system works

Prices

Each SKU has a current price in cents. SKUs are stored in upper case; any SKU in a request or a feed is trimmed and upper-cased first. A SKU without a known price is an unknown product.

Alerts

  • Create (customer, SKU, target in cents):

    1. the product must have a known price (404 UNKNOWN_PRODUCT);
    2. the target must be more than 0 (400 INVALID_TARGET);
    3. the target must be below the current price (400 TARGET_NOT_BELOW_PRICE);
    4. the customer may not already have an ACTIVE alert for that SKU (409 DUPLICATE_ALERT);
    5. a customer may have at most 10 ACTIVE alerts (409 TOO_MANY_ALERTS); triggered and cancelled alerts don't count.

    A new alert is ACTIVE, with id AL-1, AL-2, ... in creation order and triggeredPriceCents 0.

  • List: a customer's own alerts (any status), sorted by SKU, then creation order.

  • Cancel: only an ACTIVE alert can be cancelled (409 NOT_ACTIVE otherwise); it becomes CANCELLED. An unknown id or another customer's alert is 404 NOT_FOUND (we don't reveal that it exists).

Price feed

Plain text, one row per line: sku,price.

sku,price
KT-100,39.99
HD-7,120
  • An optional header row (the first non-blank line, if it starts with sku in any case) is skipped; blank lines are ignored; fields are trimmed.
  • Exactly 2 fields; the SKU must not be empty; the price is dollars (1–7 digits, optionally . and 1 or 2 digits) and more than 0.
  • One bad line rejects the whole feed (400 INVALID_FEED) and nothing is applied.
  • Rows are applied in order (a SKU may appear more than once; each row sets the price). New SKUs are added.
  • After each row, every ACTIVE alert for that SKU whose target is at or above the new price (the price is at or below the target) becomes TRIGGERED, recording that price. An alert triggers only once.
  • The result says how many rows were applied and which alerts triggered, in order.

API

Method and pathBodySuccess
POST /api/alerts{sku, targetCents}201 alert
GET /api/alerts200 my alerts
DELETE /api/alerts/{id}200 the cancelled alert
POST /api/prices/feedthe feed, Content-Type: text/plain200 {updated, triggered: [ids]}
GET /api/prices/{sku}200 {sku, priceCents}; 404 UNKNOWN_PRODUCT

The alert endpoints need an X-Customer-Id header. An alert is {id, customerId, sku, targetCents, status, triggeredPriceCents}.

Errors

Errors return {"error": "<CODE>", "message": "..."} with the statuses above. A missing header, a blank sku or malformed JSON is 400 INVALID_REQUEST.

Project structure

src/main/java/com/bugnik/pricealerts/
  PriceAlertsApplication.java       Spring Boot entry point
  model/                            Alert, AlertStatus, PriceUpdate
  repository/                       in-memory AlertRepository and PriceRepository
  service/AlertService.java         create / list / cancel rules
  service/FeedService.java          applying a feed and triggering alerts
  service/AlertException.java       business errors (status + code)
  util/PriceFeedParser.java         reads the feed text (throws FeedFormatException)
  web/                              AlertController, ApiError, ApiExceptionHandler
src/test/java/com/bugnik/pricealerts/   unit and MockMvc tests

Your task

Customers and support have reported problems since the last release:

  • The project no longer builds.
  • A customer with a $39.99 target isn't notified when the price drops to exactly $39.99.
  • Cancelling an alert that doesn't exist, or belongs to someone else, returns a server error instead of 404.

Find and fix the defects so that all tests pass.

  • Do not modify src/test/ or pom.xml.
  • Keep your changes minimal. Fix the defects; don't rewrite modules.
  • Additional hidden tests check the behaviour described in this README.