Skip to content

Offer Feed Criteria

This page describes the requirements and validation rules that iUsed applies to Refurbisher Offer Feeds during import. It is intended for the iUsed team and Flooris developers involved in onboarding or troubleshooting Refurbisher integrations.

Partner-facing documentation

The full technical specification for Refurbisher partners is published at the iUsed Partner Documentation portal:

https://partner-docs.refurbishedcompany.com


How the import works

The IRP polls each active Refurbisher's offer feed approximately every 5 minutes via ImportRefurbisherOffersJob. The job:

  1. Fetches all offers from the Refurbisher's endpoint (HTTP or sFTP)
  2. Maps the raw feed fields to IRP fields using the Refurbisher's connector config
  3. Upserts each offer using (refurbisher_id, sku, ean) as the identity key
  4. Validates each offer via RefurbisherOfferValidationService
  5. Sets stock_available = 0 on any offer not present in the current feed

Identity key

Each RefurbisherOffer record is uniquely identified by the combination:

refurbisher_id + sku + ean

EAN is part of the identity

If a Refurbisher submits a different EAN for an existing SKU, the IRP creates a new separate offer record — it does not update the existing one. The old offer will have its stock set to 0. The new offer is immediately flagged as * rejected* and requires manual review.

This is intentional: an EAN change may indicate a product substitution, re-packaging, or supplier error — all of which require human judgement before the product goes live.


Field requirements

Field DB column Type Max length Required Notes
sku sku varchar(255) 255 Yes Unique per Refurbisher
ean ean varchar(25) 25 No Part of identity key
name name string Yes Product name
stock_available stock_available integer Yes 0 = out of stock
price_purchase_amount price_purchase_amount integer (cents) Yes Stored after VAT/margin deduction
price_consumer_amount price_consumer_amount integer (cents) Yes Consumer-facing price
tax_percentage tax_percentage decimal No Fallback from connector config
currency_iso currency_iso varchar(3) No Defaults to EUR

Validation rules

The RefurbisherOfferValidationService runs after every create or update. Validation is applied to the raw feed data ** (before database write) for length checks, and to the persisted model** for duplicate checks.

Rule Checked against Trigger
SKU exceeds 255 characters Raw feed value Rejected
EAN exceeds 25 characters Raw feed value Rejected
Duplicate SKU with different EAN Persisted DB records Rejected

Why raw feed data for length checks?

MySQL silently truncates strings that exceed the column length. Checking strlen() on the already-saved model would always pass (the value is already truncated). Validation therefore runs against the unmapped feed value before any DB write.

Rejected offers:

  • Have validation_status = 'rejected'
  • Have validation_message (JSON array) with one or more human-readable reasons
  • Are visible on the Refurbisher Offer index page and filterable by validation status
  • Are not pushed to Shopware until the issue is resolved or the offer is manually approved

Viewing validation results

In the IRP:

  • Navigate to Refurbisher Offers — filter by Validation status: Rejected
  • Open any rejected offer to see the specific rejection reason(s)

In the reporting cache:

Each import run produces a report at:

/reporting/refurbisher_offers/{refurbisher_id}/{import_uuid}

The report includes a rejected_offers count and detailed event log.


Common issues

Duplicate SKU with changed EAN

Symptom: An offer appears as rejected with the message "Duplicate SKU: another offer exists for this SKU with a different EAN code."

Cause: The Refurbisher has changed the EAN associated with a SKU that already exists in the IRP.

Resolution:

  1. Confirm with the Refurbisher whether the EAN change is intentional.
  2. If intentional: soft-delete the old offer (if not linked to a ProductVariant) and approve the new offer.
  3. If the old offer is linked to a ProductVariant: re-link the ProductVariant to the new offer, then soft-delete the old offer.
  4. If the EAN change is an error: ask the Refurbisher to correct the feed and revert to the original EAN.

SKU or EAN too long

Symptom: An offer is rejected with "SKU exceeds maximum length" or "EAN exceeds maximum length".

Cause: The Refurbisher's feed contains a value that is longer than the database column allows.

Resolution: Contact the Refurbisher and request a shorter identifier. The IRP cannot truncate values automatically because that would corrupt the identity key.

Offers not disappearing after stock runs out

Cause: The Refurbisher is submitting a partial feed (only changed offers) instead of the full catalogue.

Resolution: The IRP requires a complete feed on every poll. Ask the Refurbisher to always include all products, with stock_available: 0 for out-of-stock items.


Database cleanup after EAN-truncation bug

Prior to the varchar(25) column expansion (migration 2026_07_04_192053), the ean column was varchar(15). EAN codes longer than 15 characters were silently truncated, causing duplicate offer records to be created on every import run.

SQL instructions for identifying and cleaning up these duplicates are in:

docs/refurbisher-offer-cleanup.md in the IRP repository.