use grabcli_core::location::Location;
use serde_json::{Value, json};
pub use grabfood::order::{Gate, gate, parse_submit};
use crate::quote::Quote;
pub fn build_submit_body(quote: &Quote, loc: &Location, extra_notes: Option<&str>) -> Value {
json!({
"deliveryNotes": loc.delivery_notes(extra_notes),
"destination": {
"coordinates": {
"latitude": loc.latitude,
"longitude": loc.longitude,
"poiID": loc.id,
},
"address": loc.address,
"addressDetail": loc.address_detail.as_deref().unwrap_or_default(),
"poiID": loc.id,
},
"paymentTypeID": quote.payment_type_id,
"cartSignature": quote.quote_signature,
"businessType": "MART",
"supportComplexMenu": true,
"mpaDetail": null,
})
}
#[cfg(test)]
mod tests {
use super::*;
use crate::api;
use grabcli_core::money::Money;
fn quote() -> Quote {
Quote {
merchant_name: "S&R".into(),
subtotal: Money(33900),
delivery_before: Money(9900),
delivery_after: Money(9900),
fees: vec![],
discounts: vec![],
tax: None,
total_before: Money(43800),
total_after: Money(43800),
eta_min: None,
quote_signature: "SIG-SECRET".into(),
payment_type_id: "PAY-1".into(),
address: "1 Example St".into(),
poi_id: "POI-X".into(),
id: "abc123abc123".into(),
}
}
fn loc() -> Location {
serde_json::from_str(
r#"{"id":"POI-X","latitude":1.0,"longitude":2.0,"address":"1 Example St","countryCode":"PH"}"#,
)
.expect("loc")
}
#[test]
fn body_is_mart_order() {
let b = build_submit_body("e(), &loc(), None);
assert_eq!(b["businessType"], "MART");
assert_eq!(b["cartSignature"], "SIG-SECRET");
assert_eq!(b["paymentTypeID"], "PAY-1");
assert_eq!(b["destination"]["coordinates"]["poiID"], "POI-X");
assert!(b["mpaDetail"].is_null());
}
#[test]
fn body_has_address_detail_and_appended_notes() {
let saved: Location = serde_json::from_str(
r#"{"id":"POI-X","latitude":1.0,"longitude":2.0,"address":"1 Example St","addressDetail":"Unit 1A, Example Tower","noteToDriver":"Leave at lobby"}"#,
)
.expect("loc");
let b = build_submit_body("e(), &saved, Some("Ring bell"));
assert_eq!(b["destination"]["addressDetail"], "Unit 1A, Example Tower");
assert_eq!(b["deliveryNotes"], "Leave at lobby; Ring bell");
let b = build_submit_body("e(), &loc(), Some("Ring bell"));
assert_eq!(b["destination"]["addressDetail"], "");
assert_eq!(b["deliveryNotes"], "Ring bell");
let r = crate::quote::redacted(&build_submit_body("e(), &saved, None));
assert_eq!(r["destination"]["addressDetail"], "<redacted>");
assert_eq!(r["deliveryNotes"], "<redacted>");
}
#[test]
fn redacted_submit_body_hides_secrets() {
let b = crate::quote::redacted(&build_submit_body("e(), &loc(), None));
let s = serde_json::to_string(&b).expect("json");
assert!(!s.contains("SIG-SECRET"));
assert!(!s.contains("1 Example St"));
assert!(!s.contains("POI-X"));
}
#[test]
fn gate_requires_matching_fresh_id() {
assert_eq!(gate("abc", Some("abc"), false, None), Gate::Proceed);
assert!(matches!(
gate("abc", Some("old"), false, None),
Gate::QuoteChanged { .. }
));
assert_eq!(gate("abc", None, false, None), Gate::NeedConfirmation);
assert_eq!(gate("abc", None, true, Some(false)), Gate::NeedConfirmation);
}
#[test]
fn submit_url_fails_closed_without_allow_ordering() {
assert!(!api::allowlist(false).is_allowed(api::ORDERS));
}
}