func (catalog *Catalog) ship_item(w http.ResponseWriter, r *http.Request) {
	item := catalog.get_item(w, r)
	if item == nil {
		return
	}
	username := r.FormValue("user")
	timestamp := r.FormValue("ts")
	qtyString := r.FormValue("qty")
	qty, err := strconv.ParseUint(qtyString, 10, 64)
	if err != nil {
		services.Http_respond_error(w, r, "Failed to parse 'qty' parameter to uint: "+err.Error(), http.StatusBadRequest)
		return
	}
	if shipment, existed, err := item.Ship(username, qty, timestamp); err != nil {
		services.Http_respond_error(w, r, "Failed to ship item: "+err.Error(), http.StatusInternalServerError)
	} else {
		var code int
		if existed {
			code = http.StatusOK
		} else {
			code = http.StatusCreated
		}
		services.Http_respond(w, r, ([]byte)(shipment.id), code)
	}
}
func (catalog *Catalog) get_item(w http.ResponseWriter, r *http.Request) *Item {
	item_name := mux.Vars(r)["name"]
	item, err := catalog.GetItem(item_name)
	if err != nil {
		services.Http_respond_error(w, r, "Failed to retrieve item: "+err.Error(), http.StatusInternalServerError)
		return nil
	} else if item == nil {
		services.Http_respond_error(w, r, "Item does not exist: "+item_name, http.StatusNotFound)
		return nil
	}
	return item
}
func (payments *Payments) get_payment(w http.ResponseWriter, r *http.Request, lockPayment bool) *Payment {
	id := mux.Vars(r)["id"]
	payment := payments.MakePayment(id)
	existed, err := payment.LoadExisting(lockPayment, true)
	if err != nil {
		services.Http_respond_error(w, r, "Error fetching payment "+id+": "+err.Error(), http.StatusInternalServerError)
		return nil
	} else if !existed {
		services.Http_respond_error(w, r, "Payment "+id+" does not exist", http.StatusNotFound)
		return nil
	}
	return payment
}
func (catalog *Catalog) get_shipment(w http.ResponseWriter, r *http.Request) *Shipment {
	shipment_id := mux.Vars(r)["id"]
	shipment := catalog.MakeShipment(shipment_id)
	existed, err := shipment.LoadExisting()
	if err != nil {
		services.Http_respond_error(w, r, "Failed to retrieve shipment: "+err.Error(), http.StatusInternalServerError)
		return nil
	} else if !existed {
		services.Http_respond_error(w, r, "Shipment does not exist: "+shipment_id, http.StatusNotFound)
		return nil
	}
	return shipment
}
func (catalog *Catalog) show_items(w http.ResponseWriter, r *http.Request) {
	if items, err := catalog.GetAllItems(); err != nil {
		services.Http_respond_error(w, r, "Error retrieving all items: "+err.Error(), http.StatusInternalServerError)
	} else {
		services.Http_respond_json(w, r, items)
	}
}
func (store *AccountStore) get_value_query(w http.ResponseWriter, r *http.Request) (float64, bool) {
	value, err := strconv.ParseFloat(r.FormValue("value"), 64)
	if err != nil {
		services.Http_respond_error(w, r, "Failed to parse 'value' parameter to float: "+err.Error(), http.StatusBadRequest)
		return 0, false
	}
	return value, true
}
func (store *AccountStore) get_account(w http.ResponseWriter, r *http.Request) *Account {
	username := mux.Vars(r)["id"]
	if account := store.GetAccount(username); account == nil {
		services.Http_respond_error(w, r, "Account not found: "+username, http.StatusNotFound)
		return nil
	} else {
		return account
	}
}
func (payments *Payments) new_payment(w http.ResponseWriter, r *http.Request) {
	value, err := strconv.ParseFloat(r.FormValue("value"), 64)
	if err != nil {
		services.Http_respond_error(w, r, "Failed to parse 'value' parameter to float: "+err.Error(), http.StatusBadRequest)
		return
	}
	username := r.FormValue("user")
	timestamp := r.FormValue("ts")
	payment, existed, err := payments.NewPayment(username, value, timestamp)
	if err != nil {
		services.Http_respond_error(w, r, "Error creating payment: "+err.Error(), http.StatusInternalServerError)
	} else {
		var code int
		if existed {
			code = http.StatusOK
		} else {
			code = http.StatusCreated
		}
		services.Http_respond(w, r, ([]byte)(payment.id), code)
	}
}
func (store *AccountStore) optionally_commit_transaction(trans *Transaction, w http.ResponseWriter, r *http.Request) bool {
	commit := false
	if commitStr := r.FormValue("commit"); commitStr == "true" {
		commit = true
	}
	if commit {
		err := trans.Commit()
		if err != nil {
			services.Http_respond_error(w, r, "Unexpected failure to commit transaction: "+err.Error(), http.StatusInternalServerError)
			return false
		}
	}
	return true
}
func (store *AccountStore) get_transaction(w http.ResponseWriter, r *http.Request) *Transaction {
	trans_id := mux.Vars(r)["id"]
	var trans *Transaction
	var ok bool
	func() {
		store.transactionsLock.Lock()
		defer store.transactionsLock.Unlock()
		trans, ok = store.transactions[trans_id]
	}()
	if !ok || trans == nil {
		services.Http_respond_error(w, r, "Transaction not found: "+trans_id, http.StatusNotFound)
		return nil
	}
	return trans
}
func (store *AccountStore) handle_transfer(w http.ResponseWriter, r *http.Request) {
	account := store.get_account(w, r)
	value, ok := store.get_value_query(w, r)
	if !ok {
		return
	}

	target := r.FormValue("target")
	if target == "" {
		services.Http_respond_error(w, r, "Need 'target' string parameter", http.StatusBadRequest)
		return
	}
	targetAccount := store.GetAccount(target)

	trans := store.NewTransaction(account, value, targetAccount)
	if store.optionally_commit_transaction(trans, w, r) {
		services.Http_respond(w, r, ([]byte)(trans.Id), http.StatusOK)
	}
}