diff --git a/exchange.lua b/exchange.lua index 32db244..1d1a1f7 100644 --- a/exchange.lua +++ b/exchange.lua @@ -115,6 +115,18 @@ AND Poster = :p_name ]=] +local refund_order_query = [=[ +UPDATE Credit +SET Balance = Balance + coalesce(( + SELECT sum(Rate * Amount) FROM Orders + WHERE Poster = :p_name + AND Type = "buy" + AND Id = :id + ), 0) +WHERE Owner = :p_name; +]=] + + local search_asc_query = [=[ SELECT * FROM Orders WHERE Exchange = :ex_name @@ -192,6 +204,22 @@ local function is_integer(num) end +local function exec_stmt(db, stmt, names) + stmt:bind_names(names) + + local res = stmt:step() + stmt:reset() + + if res == sqlite3.BUSY then + return false, "Database Busy." + elseif res ~= sqlite3.DONE then + sql_error(db:errmsg()) + else + return true + end +end + + function exports.open_exchange(path) local db = assert(sqlite3.open(path)) @@ -215,6 +243,7 @@ function exports.open_exchange(path) del_order_stmt = assert(db:prepare(del_order_query)), reduce_order_stmt = assert(db:prepare(reduce_order_query)), cancel_order_stmt = assert(db:prepare(cancel_order_query)), + refund_order_stmt = assert(db:prepare(refund_order_query)), insert_inbox_stmt = assert(db:prepare(insert_inbox_query)), view_inbox_stmt = assert(db:prepare(view_inbox_query)), get_inbox_stmt = assert(db:prepare(get_inbox_query)), @@ -561,19 +590,22 @@ function ex_methods.cancel_order(self, p_name, id) } local db = self.db - local stmt = self.stmts.cancel_order_stmt + db:exec("BEGIN TRANSACTION;") - stmt:bind_values(params) + local refund_stmt = self.stmts.refund_order_stmt + local cancel_stmt = self.stmts.cancel_order_stmt - local res = stmt:step() - if res == sqlite3.BUSY then - stmt:reset() - return false, "Database busy." - elseif res ~= sqlite3.DONE then - sql_error(db:errmsg()) + local ref_succ, ref_err = exec_stmt(db, refund_stmt, params) + if not ref_succ then + db:exec("ROLLBACK") + return false, ref_err end - stmt:reset() + local canc_succ, canc_err = exec_stmt(db, cancel_stmt, params) + if not canc_succ then + db:exec("ROLLBACK") + return false, canc_err + end return true end @@ -789,6 +821,7 @@ function ex_methods.sell(self, p_name, ex_name, item_name, amount, rate) db:exec("BEGIN TRANSACTION"); local remaining = amount + local revenue = 0 local del_stmt = self.stmts.del_order_stmt local red_stmt = self.stmts.reduce_order_stmt @@ -847,6 +880,7 @@ function ex_methods.sell(self, p_name, ex_name, item_name, amount, rate) end remaining = remaining - row_amount + revenue = revenue + row_amount * row.Rate else -- row_amount > remaining red_stmt:bind_values(remaining, row.Id) @@ -891,6 +925,7 @@ function ex_methods.sell(self, p_name, ex_name, item_name, amount, rate) end remaining = 0 + revenue = revenue + remaining * row.Rate end if remaining == 0 then break end @@ -898,8 +933,6 @@ function ex_methods.sell(self, p_name, ex_name, item_name, amount, rate) search_stmt:reset() - local sold = amount - remaining - local revenue = sold * rate local ch_succ, ch_err = self:change_balance(p_name, revenue) if not ch_succ then db:exec("ROLLBACK;") diff --git a/exchange_machine.lua b/exchange_machine.lua index 7b3119c..320e3dc 100644 --- a/exchange_machine.lua +++ b/exchange_machine.lua @@ -96,12 +96,12 @@ local function mk_main_fs(p_name, new_item, err_str, success) local bal = exchange:get_balance(p_name) if bal then - fs = fs .. "label[0.2,0.5;Balance: " .. bal + fs = fs .. "label[0,0;Balance: " .. bal .. "]" else fs = fs .. "label[0.2,0.5;Use an ATM to make your account.]" end - fs = fs .. "button[6,0,2,1;your_orders;Your Orders]" + fs = fs .. "button[6,0;2,1;your_orders;Your Orders]" fs = fs .. "field[0.2,1.5;3,1;item;Item: ;" .. item_def .. "]" fs = fs .. "field[3.2,1.5;3,1;amount;Amount: ;" .. amount_def .. "]" fs = fs .. "button[6,1;2,1.4;select_item;Select Item]" @@ -232,6 +232,8 @@ local function mk_own_orders_fs(p_name, results, selected) fs = fs .. table_from_results(results, 0, 2, 8, 4.5, selected or "") fs = fs .. "button[0,7;2,1;cancel;Cancel]" fs = fs .. "button[3,7;2,1;back;Back]" + + return fs end @@ -445,10 +447,26 @@ local function handle_own_orders(player, formname, fields) if fields["cancel"] and idx then local row = results[idx] + if not row then return true end + local p_inv = player:get_inventory() + + local amount = row.Amount + local item = row.Item + local stack = ItemStack(item) + stack:set_count(amount) + if row.Type == "sell" then + if not p_inv:room_for_item("main", stack) then + show_own_orders(p_name, state.own_results, "Not enough room.") + return true + end + end local succ, err = exchange:cancel_order(p_name, row.Id) if succ then table.remove(results, idx) + if row.Type == "sell" then + p_inv:add_item("main", stack) + end else -- Refresh the results, since there might have been a problem. state.own_results = exchange:search_player_orders(p_name) or {} @@ -461,7 +479,7 @@ local function handle_own_orders(player, formname, fields) local event = minetest.explode_table_event(fields["result_table"]) if event.type == "CHG" then state.selected_index = event.row - 1 - show_own_orders(p_name, results, state.selected_index) + show_own_orders(p_name, results, event.row) end end