upload delivery info from gui - untested

This commit is contained in:
creating2morrow 2023-12-16 20:04:18 -05:00
parent 6340119435
commit b94802711c
4 changed files with 141 additions and 22 deletions

View file

@ -9,7 +9,8 @@ use crate::{
monero, monero,
order, order,
product, product,
utils, reqres, reqres,
utils,
}; };
use log::{ use log::{
debug, debug,
@ -189,6 +190,33 @@ pub async fn find_all_customer_orders(cid: String) -> Vec<Order> {
orders orders
} }
/// Lookup all orders for vendor
pub fn find_all_vendor_orders() -> Vec<Order> {
info!("lookup orders for vendor");
let i_s = db::Interface::open();
let i_list_key = crate::ORDER_LIST_DB_KEY;
let i_r = db::Interface::read(&i_s.env, &i_s.handle, &String::from(i_list_key));
if i_r == utils::empty_string() {
error!("order index not found");
}
let i_v_oid = i_r.split(",");
let i_v: Vec<String> = i_v_oid.map(|s| String::from(s)).collect();
let mut orders: Vec<Order> = Vec::new();
let vendor_b32: String = i2p::get_destination(None);
for o in i_v {
let order: Order = find(&o);
if order.orid != utils::empty_string() && order.cid != vendor_b32 {
// TODO(c2m): separate functionality for archived orders
if order.status != order::StatusType::Cancelled.value()
&& order.status != order::StatusType::Delivered.value()
{
orders.push(order);
}
}
}
orders
}
/// Modify order from admin server /// Modify order from admin server
pub fn modify(o: Json<Order>) -> Order { pub fn modify(o: Json<Order>) -> Order {
info!("modify order: {}", &o.orid); info!("modify order: {}", &o.orid);
@ -436,7 +464,9 @@ pub async fn finalize_order(orid: &String) -> reqres::FinalizeOrderResponse {
address, address,
..Default::default() ..Default::default()
}; };
let valid = m_describe.result.desc[0].recepients.contains(&check_destination) let valid = m_describe.result.desc[0]
.recepients
.contains(&check_destination)
&& m_describe.result.desc[0].unlock_time < monero::LockTimeLimit::Blocks.value(); && m_describe.result.desc[0].unlock_time < monero::LockTimeLimit::Blocks.value();
if !valid { if !valid {
monero::close_wallet(orid, &wallet_password).await; monero::close_wallet(orid, &wallet_password).await;
@ -450,6 +480,7 @@ pub async fn finalize_order(orid: &String) -> reqres::FinalizeOrderResponse {
error!("order wallet not swept"); error!("order wallet not swept");
return Default::default(); return Default::default();
} }
monero::close_wallet(orid, &wallet_password).await;
m_order.status = order::StatusType::Delivered.value(); m_order.status = order::StatusType::Delivered.value();
order::modify(Json(m_order)); order::modify(Json(m_order));
reqres::FinalizeOrderResponse { reqres::FinalizeOrderResponse {
@ -475,9 +506,7 @@ pub async fn transmit_finalize_request(
let proxy = reqwest::Proxy::http(&host)?; let proxy = reqwest::Proxy::http(&host)?;
let client = reqwest::Client::builder().proxy(proxy).build(); let client = reqwest::Client::builder().proxy(proxy).build();
match client? match client?
.post(format!( .post(format!("http://{}/market/order/finalize/{}", contact, orid))
"http://{}/market/order/finalize/{}", contact, orid
))
.header("proof", jwp) .header("proof", jwp)
.send() .send()
.await .await
@ -500,7 +529,11 @@ pub async fn transmit_finalize_request(
/// A post-decomposition trigger for the finalize request so that the logic /// A post-decomposition trigger for the finalize request so that the logic
/// ///
/// can be executed from the gui. /// can be executed from the gui.
pub async fn trigger_finalize_request(contact: &String, jwp: &String, orid: &String) -> reqres::FinalizeOrderResponse { pub async fn trigger_finalize_request(
contact: &String,
jwp: &String,
orid: &String,
) -> reqres::FinalizeOrderResponse {
info!("executing trigger_finalize_request"); info!("executing trigger_finalize_request");
let finalize = transmit_finalize_request(contact, jwp, orid).await; let finalize = transmit_finalize_request(contact, jwp, orid).await;
// cache finalize order request to db // cache finalize order request to db
@ -516,7 +549,10 @@ pub async fn trigger_finalize_request(contact: &String, jwp: &String, orid: &Str
} }
/// Decomposition trigger for `finalize_order()` /// Decomposition trigger for `finalize_order()`
pub async fn d_trigger_finalize_request(contact: &String, orid: &String) -> reqres::FinalizeOrderResponse { pub async fn d_trigger_finalize_request(
contact: &String,
orid: &String,
) -> reqres::FinalizeOrderResponse {
// ugh, sorry seems we need to get jwp for vendor from fts cache // ugh, sorry seems we need to get jwp for vendor from fts cache
// get jwp from db // get jwp from db
let s = db::Interface::async_open().await; let s = db::Interface::async_open().await;

View file

@ -320,7 +320,7 @@ impl eframe::App for HomeApp {
self.connections.is_i2p_advanced = !self.connections.is_i2p_advanced; self.connections.is_i2p_advanced = !self.connections.is_i2p_advanced;
log::debug!("is i2p advanced mode: {}", self.connections.is_i2p_advanced); log::debug!("is i2p advanced mode: {}", self.connections.is_i2p_advanced);
} }
// TODO: mainnet // TODO(c2m): uncomment this to add mainnet flag to gui
// let mut is_mainnet = self.connections.mainnet; // let mut is_mainnet = self.connections.mainnet;
// if ui.checkbox(&mut is_mainnet, "mainnet").changed() { // if ui.checkbox(&mut is_mainnet, "mainnet").changed() {
// self.connections.mainnet = !self.connections.mainnet; // self.connections.mainnet = !self.connections.mainnet;

View file

@ -81,6 +81,7 @@ pub struct MarketApp {
is_showing_vendor_status: bool, is_showing_vendor_status: bool,
is_showing_vendors: bool, is_showing_vendors: bool,
is_timeout: bool, is_timeout: bool,
is_uploading_dinfo: bool,
is_vendor_enabled: bool, is_vendor_enabled: bool,
is_window_shopping: bool, is_window_shopping: bool,
msig: MultisigManagement, msig: MultisigManagement,
@ -117,12 +118,15 @@ pub struct MarketApp {
cancel_request_rx: Receiver<models::Order>, cancel_request_rx: Receiver<models::Order>,
// ship_request_tx: Sender<models::Order>, // ship_request_tx: Sender<models::Order>,
// ship_request_rx: Receiver<models::Order>, // ship_request_rx: Receiver<models::Order>,
upload_dinfo_tx: Sender<bool>,
upload_dinfo_rx: Receiver<bool>,
s_contact: models::Contact, s_contact: models::Contact,
s_order: models::Order, s_order: models::Order,
vendor_status: utils::ContactStatus, vendor_status: utils::ContactStatus,
vendors: Vec<models::Contact>, vendors: Vec<models::Contact>,
order_xmr_address_tx: Sender<reqres::XmrRpcAddressResponse>, order_xmr_address_tx: Sender<reqres::XmrRpcAddressResponse>,
order_xmr_address_rx: Receiver<reqres::XmrRpcAddressResponse>, order_xmr_address_rx: Receiver<reqres::XmrRpcAddressResponse>,
upload_dinfo_str: String,
} }
impl Default for MarketApp { impl Default for MarketApp {
@ -145,6 +149,7 @@ impl Default for MarketApp {
let (order_xmr_address_tx, order_xmr_address_rx) = std::sync::mpsc::channel(); let (order_xmr_address_tx, order_xmr_address_rx) = std::sync::mpsc::channel();
let (order_funded_tx, order_funded_rx) = std::sync::mpsc::channel(); let (order_funded_tx, order_funded_rx) = std::sync::mpsc::channel();
let (submit_txset_tx, submit_txset_rx) = std::sync::mpsc::channel(); let (submit_txset_tx, submit_txset_rx) = std::sync::mpsc::channel();
let (upload_dinfo_tx, upload_dinfo_rx) = std::sync::mpsc::channel();
let contents = std::fs::read("./assets/qr.png").unwrap_or(Vec::new()); let contents = std::fs::read("./assets/qr.png").unwrap_or(Vec::new());
MarketApp { MarketApp {
contact_info_rx, contact_info_rx,
@ -176,6 +181,7 @@ impl Default for MarketApp {
is_showing_vendor_status: false, is_showing_vendor_status: false,
is_showing_vendors: false, is_showing_vendors: false,
is_timeout: false, is_timeout: false,
is_uploading_dinfo: false,
is_vendor_enabled, is_vendor_enabled,
is_window_shopping: false, is_window_shopping: false,
msig: Default::default(), msig: Default::default(),
@ -221,6 +227,9 @@ impl Default for MarketApp {
submit_txset_tx, submit_txset_tx,
vendor_status: Default::default(), vendor_status: Default::default(),
vendors: Vec::new(), vendors: Vec::new(),
upload_dinfo_str: utils::empty_string(),
upload_dinfo_rx,
upload_dinfo_tx,
} }
} }
} }
@ -339,6 +348,13 @@ impl eframe::App for MarketApp {
self.is_loading = false; self.is_loading = false;
} }
if let Ok(upload_dinfo) = self.upload_dinfo_rx.try_recv() {
if !upload_dinfo {
log::error!("failure to upload delivery info")
}
self.is_loading = false;
}
// Vendor status window // Vendor status window
//----------------------------------------------------------------------------------- //-----------------------------------------------------------------------------------
let mut is_showing_vendor_status = self.is_showing_vendor_status; let mut is_showing_vendor_status = self.is_showing_vendor_status;
@ -776,6 +792,7 @@ impl eframe::App for MarketApp {
self.is_showing_decrypted_delivery_info = false; self.is_showing_decrypted_delivery_info = false;
} }
}); });
// View orders - Customer Order Flow Management // View orders - Customer Order Flow Management
//----------------------------------------------------------------------------------- //-----------------------------------------------------------------------------------
let mut is_customer_viewing_orders = self.is_customer_viewing_orders; let mut is_customer_viewing_orders = self.is_customer_viewing_orders;
@ -937,7 +954,6 @@ impl eframe::App for MarketApp {
gpg::encrypt(self.vendor_status.i2p.clone(), &address_bytes); gpg::encrypt(self.vendor_status.i2p.clone(), &address_bytes);
let new_order = reqres::OrderRequest { let new_order = reqres::OrderRequest {
cid: String::from(&self.new_order.cid), cid: String::from(&self.new_order.cid),
// TODO: inject mediator for vendor dispute handling
mediator: String::from(&mediator), mediator: String::from(&mediator),
pid: String::from(&self.new_order.pid), pid: String::from(&self.new_order.pid),
ship_address: encrypted_shipping_address.unwrap_or(Vec::new()), ship_address: encrypted_shipping_address.unwrap_or(Vec::new()),
@ -967,6 +983,47 @@ impl eframe::App for MarketApp {
} }
}); });
// Vendor Upload Delivery Info Form
//-----------------------------------------------------------------------------------
let mut is_uploading_dinfo = self.is_uploading_dinfo;
egui::Window::new("upload dinfo form")
.open(&mut is_uploading_dinfo)
.title_bar(false)
.vscroll(true)
.show(&ctx, |ui| {
ui.heading("Upload DINFO Form");
if self.is_loading {
ui.add(egui::Spinner::new());
ui.label("triggering NASR, just a moment...");
}
ui.label(format!("order id: {}", self.new_order.orid));
ui.horizontal(|ui| {
let delivery_info = ui.label("delivery info: ");
ui.text_edit_singleline(&mut self.upload_dinfo_str)
.labelled_by(delivery_info.id);
});
if self.new_order.orid != utils::empty_string()
&& self.upload_dinfo_str != utils::empty_string() {
if ui.button("Trigger NASR").clicked() {
// upload delivery info
let dinfo_str = String::from(&self.upload_dinfo_str);
upload_dinfo_req(
dinfo_str.into_bytes().iter().cloned().collect(),
self.new_order.orid.clone(),
ctx.clone(),
self.upload_dinfo_tx.clone(),
);
self.new_order = Default::default();
}
}
ui.label("\n");
if ui.button("Exit").clicked() {
self.is_uploading_dinfo = false;
self.upload_dinfo_str = Default::default();
self.is_loading = false;
}
});
// View vendors // View vendors
//----------------------------------------------------------------------------------- //-----------------------------------------------------------------------------------
let mut is_showing_vendors = self.is_showing_vendors; let mut is_showing_vendors = self.is_showing_vendors;
@ -1430,18 +1487,22 @@ impl eframe::App for MarketApp {
.column(Column::initial(100.0).at_least(40.0).clip(true)) .column(Column::initial(100.0).at_least(40.0).clip(true))
.column(Column::initial(100.0).at_least(40.0).clip(true)) .column(Column::initial(100.0).at_least(40.0).clip(true))
.column(Column::remainder()) .column(Column::remainder())
.column(Column::remainder())
.min_scrolled_height(0.0); .min_scrolled_height(0.0);
table table
.header(20.0, |mut header| { .header(20.0, |mut header| {
header.col(|ui| { header.col(|ui| {
ui.strong(""); ui.strong("CID");
}); });
header.col(|ui| { header.col(|ui| {
ui.strong(""); ui.strong("Status");
}); });
header.col(|ui| { header.col(|ui| {
ui.strong(""); ui.strong("Date");
});
header.col(|ui| {
ui.strong("Payout Address");
}); });
header.col(|ui| { header.col(|ui| {
ui.strong(""); ui.strong("");
@ -1468,13 +1529,27 @@ impl eframe::App for MarketApp {
}); });
row.col(|ui| { row.col(|ui| {
ui.style_mut().wrap = Some(false); ui.style_mut().wrap = Some(false);
ui.horizontal(|ui| {
if o.status != order::StatusType::Shipped.value() {
if ui.button("Upload DINFO").clicked() {
self.new_order.orid = String::from(&o.orid);
self.is_uploading_dinfo = true;
}
}
});
ui.horizontal(|_ui| { ui.horizontal(|_ui| {
// update button // TODO: update functionality on orders not yet shipped
}); });
}); });
}); });
} }
}); });
ui.horizontal(|ui| {
if ui.button("Exit").clicked() {
self.is_showing_orders = false;
self.is_loading = false;
}
});
}); });
// End Vendor specific // End Vendor specific
@ -1584,7 +1659,8 @@ impl eframe::App for MarketApp {
} }
ui.label("\n"); ui.label("\n");
if ui.button("Manage Orders").clicked() { if ui.button("Manage Orders").clicked() {
// TODO(c2m): vendor order management logic self.is_showing_orders = true;
self.orders = order::find_all_vendor_orders();
} }
} }
}); });
@ -2300,12 +2376,7 @@ fn validate_msig_step(
m_info != utils::empty_string() && v_info != utils::empty_string() m_info != utils::empty_string() && v_info != utils::empty_string()
} }
fn release_txset( fn release_txset(contact: String, orid: String, ctx: egui::Context, tx: Sender<bool>) {
contact: String,
orid: String,
ctx: egui::Context,
tx: Sender<bool>,
) {
tokio::spawn(async move { tokio::spawn(async move {
log::info!("async release txset"); log::info!("async release txset");
let lookup = order::find(&orid); let lookup = order::find(&orid);
@ -2322,3 +2393,12 @@ fn release_txset(
todo!() todo!()
}); });
} }
fn upload_dinfo_req(dinfo: Vec<u8>, orid: String, ctx: egui::Context, tx: Sender<bool>) {
tokio::spawn(async move {
log::info!("async upload_dinfo_req");
let dinfo = order::upload_delivery_info(&orid, &dinfo).await;
let _ = tx.send(dinfo.orid != utils::empty_string());
ctx.request_repaint();
});
}

View file

@ -246,7 +246,10 @@ pub async fn cancel_order(
/// ///
/// Protected: true /// Protected: true
#[post("/order/finalize/<orid>")] #[post("/order/finalize/<orid>")]
pub async fn finalize_order(orid: String, _jwp: proof::PaymentProof) -> Custom<Json<reqres::FinalizeOrderResponse>> { pub async fn finalize_order(
orid: String,
_jwp: proof::PaymentProof,
) -> Custom<Json<reqres::FinalizeOrderResponse>> {
let finalize = order::finalize_order(&orid).await; let finalize = order::finalize_order(&orid).await;
if !finalize.vendor_update_success { if !finalize.vendor_update_success {
return Custom(Status::BadRequest, Json(Default::default())); return Custom(Status::BadRequest, Json(Default::default()));