mirror of
https://github.com/wasrusgen/wasrusgen1-crm.git
synced 2026-06-03 17:44:46 +00:00
feat: delete client — removes project with all data (messages/models/artifacts/docs)
This commit is contained in:
parent
9f63f3dd46
commit
c37491cbc7
@ -616,6 +616,26 @@ def update_crm():
|
|||||||
save_artifact(proj["id"], "crm", crm)
|
save_artifact(proj["id"], "crm", crm)
|
||||||
return jsonify({"ok": True, "crm": crm})
|
return jsonify({"ok": True, "crm": crm})
|
||||||
|
|
||||||
|
@app.route("/api/project/delete", methods=["POST"])
|
||||||
|
def delete_project():
|
||||||
|
data = request.get_json(force=True) or {}
|
||||||
|
proj = get_project(data.get("token"))
|
||||||
|
if not proj:
|
||||||
|
return jsonify({"error": "project not found"}), 404
|
||||||
|
pid = proj["id"]
|
||||||
|
con = db()
|
||||||
|
con.execute("DELETE FROM messages WHERE project_id=?", (pid,))
|
||||||
|
con.execute("DELETE FROM models WHERE project_id=?", (pid,))
|
||||||
|
con.execute("DELETE FROM artifacts WHERE project_id=?", (pid,))
|
||||||
|
con.execute("DELETE FROM projects WHERE id=?", (pid,))
|
||||||
|
con.commit()
|
||||||
|
# удалить загруженные документы
|
||||||
|
import shutil
|
||||||
|
pdir = os.path.join(UPLOAD_DIR, proj["token"])
|
||||||
|
if os.path.isdir(pdir):
|
||||||
|
shutil.rmtree(pdir, ignore_errors=True)
|
||||||
|
return jsonify({"ok": True})
|
||||||
|
|
||||||
@app.route("/api/project/tasks", methods=["POST"])
|
@app.route("/api/project/tasks", methods=["POST"])
|
||||||
def update_tasks():
|
def update_tasks():
|
||||||
data = request.get_json(force=True) or {}
|
data = request.get_json(force=True) or {}
|
||||||
|
|||||||
@ -211,7 +211,7 @@ function renderClient(){
|
|||||||
<div class="cc-field"><div class="cc-fl">Оплачено</div><input class="cc-fi" id="cpPaid" type="number" value="${crm.paid_amount||''}" placeholder="0" onchange="saveCrm()"></div>
|
<div class="cc-field"><div class="cc-fl">Оплачено</div><input class="cc-fi" id="cpPaid" type="number" value="${crm.paid_amount||''}" placeholder="0" onchange="saveCrm()"></div>
|
||||||
<div class="cc-field"><div class="cc-fl">Источник</div><input class="cc-fi" id="cpSrc" value="${esc(crm.source)}" placeholder="откуда пришёл" onchange="saveCrm()"></div>
|
<div class="cc-field"><div class="cc-fl">Источник</div><input class="cc-fi" id="cpSrc" value="${esc(crm.source)}" placeholder="откуда пришёл" onchange="saveCrm()"></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="cc-actions"><button class="btn btn-p" onclick="inviteLink()">🔗 Ссылка клиенту</button><a class="btn btn-g" href="cabinet.html?t=${current}" target="_blank">👁 Открыть кабинет</a></div>
|
<div class="cc-actions"><button class="btn btn-p" onclick="inviteLink()">🔗 Ссылка клиенту</button><a class="btn btn-g" href="cabinet.html?t=${current}" target="_blank">👁 Открыть кабинет</a><button class="btn btn-g" style="margin-left:auto;border-color:#FECACA;color:#DC2626" onclick="deleteClient()">🗑 Удалить клиента</button></div>
|
||||||
<div id="tasksBox"></div>
|
<div id="tasksBox"></div>
|
||||||
<div class="tabs">${TABS.map(t=>`<div class="tab ${t.id===activeTab?'active':''} ${approved(t.id)?'done':''}" onclick="setTab('${t.id}')">${t.icon} ${t.name}</div>`).join("")}</div>
|
<div class="tabs">${TABS.map(t=>`<div class="tab ${t.id===activeTab?'active':''} ${approved(t.id)?'done':''}" onclick="setTab('${t.id}')">${t.icon} ${t.name}</div>`).join("")}</div>
|
||||||
<div id="tabContent"></div>`;
|
<div id="tabContent"></div>`;
|
||||||
@ -240,6 +240,12 @@ async function saveCrm(){
|
|||||||
await loadProjects();
|
await loadProjects();
|
||||||
}
|
}
|
||||||
function inviteLink(){const url=`${location.origin}${location.pathname.replace('crm.html','cabinet.html')}?t=${current}`;navigator.clipboard.writeText(url).then(()=>alert("Ссылка скопирована:\n\n"+url)).catch(()=>prompt("Ссылка:",url));}
|
function inviteLink(){const url=`${location.origin}${location.pathname.replace('crm.html','cabinet.html')}?t=${current}`;navigator.clipboard.writeText(url).then(()=>alert("Ссылка скопирована:\n\n"+url)).catch(()=>prompt("Ссылка:",url));}
|
||||||
|
async function deleteClient(){
|
||||||
|
const nm=state.client_name||"клиента";
|
||||||
|
if(!confirm(`Удалить «${nm}» со всеми данными (интервью, анализ, ТЗ, документы)?\n\nЭто действие необратимо.`))return;
|
||||||
|
await fetch(`${API}/api/project/delete`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({token:current})});
|
||||||
|
current=null;await loadProjects();setView("dashboard");
|
||||||
|
}
|
||||||
|
|
||||||
function exportSpecPDF(){
|
function exportSpecPDF(){
|
||||||
const s=state.spec;if(!s){alert("ТЗ ещё не собрано");return}
|
const s=state.spec;if(!s){alert("ТЗ ещё не собрано");return}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user