Lines
61.33 %
Functions
54.55 %
Branches
100 %
//! Transaction-edit open + submit logic for `App`.
use cli_core::eval::escape_str;
use cli_core::forms::{
EditableTransaction, LogicalSplitInput, build_transaction_update_payload,
parse_editable_transaction,
};
use crate::app::App;
use crate::form::Form;
use crate::modal::Modal;
use crate::route::RouteCtx;
use crate::view::ViewId;
impl App {
/// Dispatch `(get-transaction-detail "<id>")` with `RouteCtx::TransactionEdit`.
///
/// The async reply opens the edit form (or sets a status on parse failure).
pub fn open_transaction_edit_async(&mut self, id: &str) {
if self.console_eval.is_none() {
self.status = "console not connected".to_string();
return;
}
let form = format!("(get-transaction-detail {})", escape_str(id));
if self
.dispatch_eval(ViewId::Transactions, RouteCtx::TransactionEdit, form)
.is_none()
{
self.status = "eval worker stopped".to_string();
/// Called from `deliver_reply` when a `TransactionEdit` route reply arrives.
pub(super) fn deliver_transaction_edit_reply(&mut self, wire: &str) {
match parse_editable_transaction(wire) {
Ok(et) => self.open_edit_form_from(&et),
Err(msg) => self.status = format!("can't edit this transaction: {msg}"),
fn open_edit_form_from(&mut self, et: &EditableTransaction) {
let mode = self.edit_mode;
self.overlays
.push(Modal::Form(Form::transaction_edit(mode, et)));
self.fetch_transaction_form_options();
/// Submit the `update-transaction-logical` payload for the edit form.
/// Returns `false` when the eval worker is absent or the payload fails to build.
pub fn submit_transaction_edit(
&mut self,
id: &str,
splits: &[LogicalSplitInput],
note: &str,
date: &str,
) -> bool {
let form = match build_transaction_update_payload(id, splits, note, date) {
Ok(f) => f,
Err(e) => {
self.status = format!("transaction payload error: {e}");
return false;
match self.dispatch_eval(
ViewId::Transactions,
RouteCtx::Mutation {
refresh: ViewId::Transactions,
},
form,
) {
Some(_) => true,
None => {
false
#[cfg(test)]
mod tests {
use super::*;
use crate::widgets::EditMode;
use sqlx::types::Uuid;
fn make_app() -> App {
App::new(Uuid::new_v4(), EditMode::Emacs)
#[test]
fn deliver_transaction_edit_reply_err_path_sets_status() {
let mut app = make_app();
// Garbage wire → parse_editable_transaction returns Err → descriptive status.
app.deliver_transaction_edit_reply("garbage wire");
assert!(
app.status.starts_with("can't edit this transaction:"),
"error reply sets descriptive status: {}",
app.status
);
assert!(app.overlays.is_empty(), "no form opened on parse error");
fn submit_transaction_edit_without_eval_sets_status() {
use cli_core::forms::LogicalSplitInput;
let splits = vec![LogicalSplitInput {
from: "from-uuid".to_string(),
to: "to-uuid".to_string(),
from_commodity: "comm-uuid".to_string(),
to_commodity: "comm-uuid".to_string(),
amount: "10".to_string(),
to_amount: None,
}];
let ok = app.submit_transaction_edit("tx-id", &splits, "note", "2024-01-01");
assert!(!ok, "no eval worker → returns false");
assert_eq!(app.status, "console not connected");