Modify Tx and Delete Tx
This commit is contained in:
parent
d373c36594
commit
38e2285ad3
@ -2,6 +2,16 @@
|
||||
<profile version="1.0">
|
||||
<option name="myName" value="Project Default" />
|
||||
<inspection_tool class="HtmlFormInputWithoutLabel" enabled="true" level="WEAK WARNING" enabled_by_default="true" editorAttributes="INFO_ATTRIBUTES" />
|
||||
<inspection_tool class="HtmlUnknownAttribute" enabled="true" level="WARNING" enabled_by_default="true">
|
||||
<option name="myValues">
|
||||
<value>
|
||||
<list size="1">
|
||||
<item index="0" class="java.lang.String" itemvalue="row-id" />
|
||||
</list>
|
||||
</value>
|
||||
</option>
|
||||
<option name="myCustomValuesEnabled" value="true" />
|
||||
</inspection_tool>
|
||||
<inspection_tool class="HtmlUnknownTarget" enabled="true" level="WEAK WARNING" enabled_by_default="true" editorAttributes="INFO_ATTRIBUTES" />
|
||||
</profile>
|
||||
</component>
|
||||
@ -10,8 +10,12 @@
|
||||
<cargoProject FILE="$PROJECT_DIR$/bookkeeper/Cargo.toml" />
|
||||
</component>
|
||||
<component name="ChangeListManager">
|
||||
<list default="true" id="76b3b902-7a5c-4bcd-9c1b-8241d748fb44" name="更改" comment="Implement add transaction">
|
||||
<list default="true" id="76b3b902-7a5c-4bcd-9c1b-8241d748fb44" name="更改" comment="Update some settings">
|
||||
<change beforePath="$PROJECT_DIR$/.idea/inspectionProfiles/Project_Default.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/inspectionProfiles/Project_Default.xml" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/bookkeeper/src/main.rs" beforeDir="false" afterPath="$PROJECT_DIR$/bookkeeper/src/main.rs" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/bookkeeper/templates/index.html.j2" beforeDir="false" afterPath="$PROJECT_DIR$/bookkeeper/templates/index.html.j2" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/bookkeeper/templates/tx.html.j2" beforeDir="false" afterPath="$PROJECT_DIR$/bookkeeper/templates/tx.html.j2" afterDir="false" />
|
||||
</list>
|
||||
<option name="SHOW_DIALOG" value="false" />
|
||||
<option name="HIGHLIGHT_CONFLICTS" value="true" />
|
||||
@ -44,30 +48,30 @@
|
||||
<option name="hideEmptyMiddlePackages" value="true" />
|
||||
<option name="showLibraryContents" value="true" />
|
||||
</component>
|
||||
<component name="PropertiesComponent"><![CDATA[{
|
||||
"keyToString": {
|
||||
"ASKED_SHARE_PROJECT_CONFIGURATION_FILES": "true",
|
||||
"Cargo.Run bookkeeper.executor": "Run",
|
||||
"DefaultHtmlFileTemplate": "HTML File",
|
||||
"RunOnceActivity.ShowReadmeOnStart": "true",
|
||||
"RunOnceActivity.git.unshallow": "true",
|
||||
"RunOnceActivity.rust.reset.selective.auto.import": "true",
|
||||
"SHARE_PROJECT_CONFIGURATION_FILES": "true",
|
||||
"git-widget-placeholder": "main",
|
||||
"last_opened_file_path": "D:/code/finance-consumer/bookkeeper/templates",
|
||||
"node.js.detected.package.eslint": "true",
|
||||
"node.js.detected.package.tslint": "true",
|
||||
"node.js.selected.package.eslint": "(autodetect)",
|
||||
"node.js.selected.package.tslint": "(autodetect)",
|
||||
"nodejs_package_manager_path": "npm",
|
||||
"org.rust.cargo.project.model.PROJECT_DISCOVERY": "true",
|
||||
"org.rust.cargo.project.model.impl.CargoExternalSystemProjectAware.subscribe.first.balloon": "",
|
||||
"org.rust.first.attach.projects": "true",
|
||||
"run.code.analysis.last.selected.profile": "pProject Default",
|
||||
"settings.editor.selected.configurable": "preferences.pluginManager",
|
||||
"vue.rearranger.settings.migration": "true"
|
||||
<component name="PropertiesComponent">{
|
||||
"keyToString": {
|
||||
"ASKED_SHARE_PROJECT_CONFIGURATION_FILES": "true",
|
||||
"Cargo.Run bookkeeper.executor": "Run",
|
||||
"DefaultHtmlFileTemplate": "HTML File",
|
||||
"RunOnceActivity.ShowReadmeOnStart": "true",
|
||||
"RunOnceActivity.git.unshallow": "true",
|
||||
"RunOnceActivity.rust.reset.selective.auto.import": "true",
|
||||
"SHARE_PROJECT_CONFIGURATION_FILES": "true",
|
||||
"git-widget-placeholder": "main",
|
||||
"last_opened_file_path": "D:/code/finance-consumer/bookkeeper/templates",
|
||||
"node.js.detected.package.eslint": "true",
|
||||
"node.js.detected.package.tslint": "true",
|
||||
"node.js.selected.package.eslint": "(autodetect)",
|
||||
"node.js.selected.package.tslint": "(autodetect)",
|
||||
"nodejs_package_manager_path": "npm",
|
||||
"org.rust.cargo.project.model.PROJECT_DISCOVERY": "true",
|
||||
"org.rust.cargo.project.model.impl.CargoExternalSystemProjectAware.subscribe.first.balloon": "",
|
||||
"org.rust.first.attach.projects": "true",
|
||||
"run.code.analysis.last.selected.profile": "pProject Default",
|
||||
"settings.editor.selected.configurable": "preferences.pluginManager",
|
||||
"vue.rearranger.settings.migration": "true"
|
||||
}
|
||||
}]]></component>
|
||||
}</component>
|
||||
<component name="RecentsManager">
|
||||
<key name="CopyFile.RECENT_KEYS">
|
||||
<recent name="D:\code\finance-consumer\bookkeeper\templates" />
|
||||
@ -146,7 +150,8 @@
|
||||
<workItem from="1735391132866" duration="1139000" />
|
||||
<workItem from="1735392290940" duration="620000" />
|
||||
<workItem from="1735392928494" duration="12910000" />
|
||||
<workItem from="1735470376833" duration="15948000" />
|
||||
<workItem from="1735470376833" duration="16014000" />
|
||||
<workItem from="1735553493290" duration="4033000" />
|
||||
</task>
|
||||
<task id="LOCAL-00001" summary="Add bookkeeper">
|
||||
<option name="closed" value="true" />
|
||||
@ -196,7 +201,15 @@
|
||||
<option name="project" value="LOCAL" />
|
||||
<updated>1735486473481</updated>
|
||||
</task>
|
||||
<option name="localTasksCounter" value="7" />
|
||||
<task id="LOCAL-00007" summary="Update some settings">
|
||||
<option name="closed" value="true" />
|
||||
<created>1735486582714</created>
|
||||
<option name="number" value="00007" />
|
||||
<option name="presentableId" value="LOCAL-00007" />
|
||||
<option name="project" value="LOCAL" />
|
||||
<updated>1735486582714</updated>
|
||||
</task>
|
||||
<option name="localTasksCounter" value="8" />
|
||||
<servers />
|
||||
</component>
|
||||
<component name="TypeScriptGeneratedFilesManager">
|
||||
@ -220,7 +233,8 @@
|
||||
<MESSAGE value="Add index page" />
|
||||
<MESSAGE value="Refine data structure and index page" />
|
||||
<MESSAGE value="Implement add transaction" />
|
||||
<option name="LAST_COMMIT_MESSAGE" value="Implement add transaction" />
|
||||
<MESSAGE value="Update some settings" />
|
||||
<option name="LAST_COMMIT_MESSAGE" value="Update some settings" />
|
||||
</component>
|
||||
<component name="XSLT-Support.FileAssociations.UIState">
|
||||
<expand />
|
||||
|
||||
@ -19,6 +19,7 @@ use sea_orm::{ActiveModelTrait, ColumnTrait, ConnectOptions, DatabaseConnection,
|
||||
use sea_orm_rocket::{rocket::figment::Figment, Config, Connection, Database};
|
||||
use std::str::FromStr;
|
||||
use std::time::Duration;
|
||||
use rocket::http::Status;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(sea_orm_rocket::Database, Debug)]
|
||||
@ -98,6 +99,49 @@ struct SplitPiece{
|
||||
volume: i32,
|
||||
}
|
||||
|
||||
#[get("/tx/<id>")]
|
||||
async fn get_tx(conn: Connection<'_, Db>, id: i32) -> Result<Template, Status> {
|
||||
let row = TE::find_by_id(id)
|
||||
.one(conn.into_inner())
|
||||
.await
|
||||
.unwrap();
|
||||
match row {
|
||||
None => { Err(Status::NotFound) },
|
||||
Some(row) => {
|
||||
Ok(Template::render("tx", context! {
|
||||
r: row,
|
||||
target: "/tx/".to_owned() + id.to_string().as_str(),
|
||||
}))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[post("/tx/<id>", data = "<data>")]
|
||||
async fn post_tx(data: Form<TransModel<'_>>, conn: Connection<'_, Db>, id: i32) -> Result<Redirect, Status> {
|
||||
dbg!(&data);
|
||||
let mut record = translate(data);
|
||||
record.id = Set(id);
|
||||
dbg!(&record);
|
||||
match record.update(conn.into_inner()).await {
|
||||
Err(_) => { Err(Status::NotFound) },
|
||||
Ok(_) => { Ok(Redirect::to("/")) },
|
||||
}
|
||||
}
|
||||
|
||||
#[delete("/tx/<id>")]
|
||||
async fn delete_tx(conn: Connection<'_, Db>, id: i32) -> Result<Redirect, Status> {
|
||||
match TE::delete_by_id(id).exec(conn.into_inner()).await {
|
||||
Err(_) => { Err(Status::InternalServerError) },
|
||||
Ok(res) => {
|
||||
if res.rows_affected == 1 {
|
||||
Ok(Redirect::to("/"))
|
||||
} else {
|
||||
Err(Status::NotFound)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[get("/add")]
|
||||
async fn get_add() -> Template {
|
||||
Template::render("tx", context! {
|
||||
@ -108,7 +152,6 @@ async fn get_add() -> Template {
|
||||
|
||||
#[post("/add", data = "<trans>")]
|
||||
async fn add(trans: Form<TransModel<'_>>, conn: Connection<'_, Db>) -> Flash<Redirect> {
|
||||
dbg!(&trans);
|
||||
let record = translate(trans);
|
||||
|
||||
record.insert(conn.into_inner()).await.unwrap();
|
||||
@ -174,5 +217,5 @@ async fn rocket() -> _ {
|
||||
.attach(Db::init())
|
||||
.attach(AdHoc::try_on_ignite("Migrations", run_migrations))
|
||||
.attach(Template::fairing())
|
||||
.mount("/", routes![index, add, get_add])
|
||||
.mount("/", routes![index, add, get_add, get_tx, post_tx, delete_tx])
|
||||
}
|
||||
|
||||
@ -39,7 +39,7 @@
|
||||
<td rowspan="{{ loop.length }}" style="vertical-align: middle;" class="{% if r.gain|float > 0 %}is-success{% else %}is-danger{% endif %}">{{ (r.gain or 0)|float|round(4) }}%</td>
|
||||
<td rowspan="{{ loop.length }}" style="vertical-align: middle;" class="{% if r.net_gain|float > 0 %}is-success{% else %}is-danger{% endif %}">{{ (r.net_gain or 0)|float|round(4) }}%</td>
|
||||
<td rowspan="{{ loop.length }}" style="vertical-align: middle;">
|
||||
<a href="#">修改</a>
|
||||
<a row-id="{{ r.id }}" class="modify-row">改</a> <a row-id="{{ r.id }}" class="delete-row has-text-danger">删</a>
|
||||
</td>
|
||||
{% else %}
|
||||
<td>{{ p.date or "" }}</td>
|
||||
@ -63,7 +63,8 @@
|
||||
<td></td>
|
||||
<td>-</td>
|
||||
<td>-</td>
|
||||
<td><a href="#">修改</a></td>
|
||||
<td><a row-id="{{ r.id }}" class="modify-row">改</a> <a row-id="{{ r.id }}" class="delete-row has-text-danger">删</a>
|
||||
</td>
|
||||
</tr>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
@ -109,6 +110,33 @@
|
||||
openModal($target);
|
||||
});
|
||||
|
||||
(document.querySelectorAll('.modify-row') || []).forEach(($cl) => {
|
||||
$cl.addEventListener('click', async () => {
|
||||
const rowId = $cl.attributes.getNamedItem("row-id").value;
|
||||
const $target = document.getElementById("modal");
|
||||
const response = await fetch(`/tx/${rowId}`);
|
||||
if (!response.ok) {
|
||||
return;
|
||||
}
|
||||
document.getElementById('modal-content').innerHTML = await response.text();
|
||||
openModal($target);
|
||||
});
|
||||
});
|
||||
|
||||
(document.querySelectorAll('.delete-row') || []).forEach(($cl) => {
|
||||
$cl.addEventListener('click', async () => {
|
||||
const rowId = $cl.attributes.getNamedItem("row-id").value;
|
||||
if (confirm(`删除${$cl.parentElement.parentElement.innerText}吗?`) !== true) {
|
||||
return;
|
||||
}
|
||||
const response = await fetch(`/tx/${rowId}`, {method: 'DELETE'});
|
||||
alert(`${response.ok ? "OK" : "Fail"}: ${response.status}`);
|
||||
if (response.ok) {
|
||||
$cl.parentElement.parentElement.remove();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// Add a click event on various child elements to close the parent modal
|
||||
(document.querySelectorAll('.modal-background, .modal-close, .modal-card-head .delete, .modal-card-foot .button') || []).forEach(($close) => {
|
||||
const $target = $close.closest('.modal');
|
||||
@ -148,6 +176,8 @@
|
||||
this_row.parentElement.removeChild(this_row);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
</script>
|
||||
|
||||
{% endblock container %}
|
||||
|
||||
@ -34,30 +34,32 @@
|
||||
<thead>
|
||||
<tr>
|
||||
<th><label class="label">卖出日期</label></th>
|
||||
<th><label class="label">买入价</label></th>
|
||||
<th><label class="label">卖出价</label></th>
|
||||
<th><label class="label">成交量</label></th>
|
||||
<th><label class="label">实际买入</label></th>
|
||||
<th><label class="label">实际卖出入</label></th>
|
||||
<th style="min-width: 4rem; vertical-align: middle;">操作</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% if r.split_pieces %}
|
||||
{% for split in r.split_pieces %}
|
||||
<tr>
|
||||
{% if r.split_pieces %}
|
||||
{% for split in r.split_pieces %}
|
||||
<td><input name="split_pieces[].date" class="input" type="date" placeholder="YYYY-MM-DD" value="{{ split.date or '' }}"></td>
|
||||
<td><input name="split_pieces[].sell" class="input" type="number" placeholder="Sell" value="{{ split.sell or '' }}"></td>
|
||||
<td><input name="split_pieces[].volume" class="input" type="number" placeholder="Volume" value="{{ split.volume or '' }}"></td>
|
||||
<td><input name="split_pieces[].net_sell" class="input" type="number" placeholder="Net Sell" value="{{ split.net_sell or '' }}"></td>
|
||||
<td><input name="split_pieces[{{ loop.index0 }}].date" class="input" type="date" placeholder="YYYY-MM-DD" value="{{ split.date or '' }}"></td>
|
||||
<td><input name="split_pieces[{{ loop.index0 }}].sell" class="input" type="number" placeholder="Sell" value="{{ split.sell or '' }}"></td>
|
||||
<td><input name="split_pieces[{{ loop.index0 }}].volume" class="input" type="number" placeholder="Volume" value="{{ split.volume or '' }}"></td>
|
||||
<td><input name="split_pieces[{{ loop.index0 }}].net_sell" class="input" type="number" placeholder="Net Sell" value="{{ split.net_sell or '' }}"></td>
|
||||
<td><a onclick="deleteRow(this)">删除</a></td>
|
||||
{% endfor %}
|
||||
{% else %}
|
||||
<td><input name="split_pieces[0].date" class="input" type="date" placeholder="YYYY-MM-DD"></td>
|
||||
<td><input name="split_pieces[0].sell" class="input" type="number" placeholder="Sell"></td>
|
||||
<td><input name="split_pieces[0].volume" class="input" type="number" placeholder="Volume"></td>
|
||||
<td><input name="split_pieces[0].net_sell" class="input" type="number" placeholder="Net Sell"></td>
|
||||
<td style="vertical-align: middle;"><a onclick="deleteRow(this)">删除</a></td>
|
||||
{% endif %}
|
||||
</tr>
|
||||
{% endfor %}
|
||||
{% else %}
|
||||
<tr>
|
||||
<td><input name="split_pieces[0].date" class="input" type="date" placeholder="YYYY-MM-DD"></td>
|
||||
<td><input name="split_pieces[0].sell" class="input" type="number" placeholder="Sell"></td>
|
||||
<td><input name="split_pieces[0].volume" class="input" type="number" placeholder="Volume"></td>
|
||||
<td><input name="split_pieces[0].net_sell" class="input" type="number" placeholder="Net Sell"></td>
|
||||
<td style="vertical-align: middle;"><a onclick="deleteRow(this)">删除</a></td>
|
||||
</tr>
|
||||
{% endif %}
|
||||
<tr class="is-light" id="add-row-line">
|
||||
<td colspan="5" style="text-align: center"><a onclick="addRow()">添加</a></td>
|
||||
</tr>
|
||||
@ -67,9 +69,6 @@
|
||||
<div class="control">
|
||||
<button class="button is-link">Submit</button>
|
||||
</div>
|
||||
<div class="control">
|
||||
<button class="button is-link is-light">Cancel</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
Loading…
Reference in New Issue
Block a user