commit 42ee62c68a81efabeefac9b08ceaac0ced52fa56
parent d8941c1e8a5d8ef69dd8d893196c9eb24c3e2de9
Author: triesap <tyson@radroots.org>
Date: Thu, 30 Apr 2026 06:32:33 +0000
replica: preserve listing discount notes
Diffstat:
2 files changed, 46 insertions(+), 5 deletions(-)
diff --git a/crates/replica_db/src/query.rs b/crates/replica_db/src/query.rs
@@ -21,6 +21,7 @@ pub struct ReplicaTradeProductSummaryRow {
pub price_qty_unit: String,
pub listing_addr: Option<String>,
pub primary_bin_id: Option<String>,
+ pub notes: Option<String>,
pub location_primary: Option<String>,
}
@@ -39,7 +40,7 @@ impl<E: SqlExecutor> ReplicaSql<E> {
&self,
lookup: &str,
) -> Result<Vec<ReplicaTradeProductSummaryRow>, SqlError> {
- let sql = "SELECT tp.id, tp.key, tp.category, tp.title, tp.summary, tp.qty_amt, tp.qty_unit, tp.qty_label, tp.qty_avail, tp.price_amt, tp.price_currency, tp.price_qty_amt, tp.price_qty_unit, tp.listing_addr, tp.primary_bin_id, loc.location_primary \
+ let sql = "SELECT tp.id, tp.key, tp.category, tp.title, tp.summary, tp.qty_amt, tp.qty_unit, tp.qty_label, tp.qty_avail, tp.price_amt, tp.price_currency, tp.price_qty_amt, tp.price_qty_unit, tp.listing_addr, tp.primary_bin_id, tp.notes, loc.location_primary \
FROM trade_product tp \
LEFT JOIN (\
SELECT tpl.tb_tp AS trade_product_id, MIN(COALESCE(gl.label, gl.gc_name, gl.gc_admin1_name, gl.gc_country_name, gl.d_tag)) AS location_primary \
@@ -79,7 +80,7 @@ impl<E: SqlExecutor> ReplicaSql<E> {
}
let sql = format!(
- "SELECT tp.id, tp.key, tp.category, tp.title, tp.summary, tp.qty_amt, tp.qty_unit, tp.qty_label, tp.qty_avail, tp.price_amt, tp.price_currency, tp.price_qty_amt, tp.price_qty_unit, tp.listing_addr, tp.primary_bin_id, loc.location_primary \
+ "SELECT tp.id, tp.key, tp.category, tp.title, tp.summary, tp.qty_amt, tp.qty_unit, tp.qty_label, tp.qty_avail, tp.price_amt, tp.price_currency, tp.price_qty_amt, tp.price_qty_unit, tp.listing_addr, tp.primary_bin_id, tp.notes, loc.location_primary \
FROM trade_product tp \
LEFT JOIN (\
SELECT tpl.tb_tp AS trade_product_id, MIN(COALESCE(gl.label, gl.gc_name, gl.gc_admin1_name, gl.gc_country_name, gl.d_tag)) AS location_primary \
diff --git a/crates/replica_sync/src/ingest.rs b/crates/replica_sync/src/ingest.rs
@@ -76,7 +76,7 @@ use radroots_replica_db_schema::trade_product::{
};
use radroots_sql_core::SqlExecutor;
use radroots_sql_core::error::SqlError;
-use serde_json::Value;
+use serde_json::{Value, json};
use crate::error::RadrootsReplicaEventsError;
use crate::event_state::{event_content_hash, event_state_key};
@@ -605,10 +605,29 @@ fn trade_product_fields_from_listing(
price_qty_unit,
listing_addr: Some(listing_addr.to_string()),
primary_bin_id: Some(listing.primary_bin_id.clone()),
- notes: None,
+ notes: trade_product_notes_from_listing(listing)?,
})
}
+fn trade_product_notes_from_listing(
+ listing: &RadrootsListing,
+) -> Result<Option<String>, RadrootsReplicaEventsError> {
+ let Some(discounts) = listing
+ .discounts
+ .as_ref()
+ .filter(|discounts| !discounts.is_empty())
+ else {
+ return Ok(None);
+ };
+ serde_json::to_string(&json!({ "listing_discounts": discounts }))
+ .map(Some)
+ .map_err(|error| {
+ RadrootsReplicaEventsError::InvalidData(format!(
+ "listing discounts could not be serialized: {error}"
+ ))
+ })
+}
+
fn primary_listing_bin(
listing: &RadrootsListing,
) -> Result<&RadrootsListingBin, RadrootsReplicaEventsError> {
@@ -2291,7 +2310,7 @@ mod tests {
let listing_d_tag = "AAAAAAAAAAAAAAAAAAAAAQ";
let listing_addr = format!("{}:{}:{}", KIND_LISTING, seller_pubkey, listing_d_tag);
- let active = listing_event(
+ let mut active = listing_event(
500,
&seller_pubkey,
10,
@@ -2299,6 +2318,21 @@ mod tests {
"active",
"Pasture Eggs",
);
+ active.tags.push(vec![
+ "radroots:discount".to_string(),
+ serde_json::json!({
+ "scope": "bin",
+ "threshold": {
+ "kind": "bin_count",
+ "amount": { "bin_id": "bin-a", "min": 1 }
+ },
+ "value": {
+ "kind": "percent",
+ "amount": { "value": "10" }
+ }
+ })
+ .to_string(),
+ ]);
assert_eq!(
radroots_replica_ingest_event(&exec, &active).expect("active ingest"),
RadrootsReplicaIngestOutcome::Applied
@@ -2319,6 +2353,12 @@ mod tests {
assert_eq!(search_rows[0].qty_avail, Some(5));
assert_eq!(search_rows[0].price_amt, 6.0);
assert_eq!(search_rows[0].price_currency, "USD");
+ assert!(
+ search_rows[0]
+ .notes
+ .as_deref()
+ .is_some_and(|notes| notes.contains("listing_discounts"))
+ );
let updated = listing_event(
501,