LOGINTECHSOL.GE
Supabase-თან კავშირი...
🏆 №1 ქონების მართვის სისტემა — საქართველო

ქონების
ჭკვიანი მართვა

LOGINTECHSOL.GE — უწყებების ინვენტარის, კომპიუტერების, ავეჯისა და სხვა ქონების სრული ციფრული მართვა. ბარკოდები, მიღება-ჩაბარება, დოკუმენტები — ყველაფერი ერთ პლატფორმაზე.

50+უწყება
10K+მართული ობიექტი
99%კმაყოფილება
24/7მხარდაჭერა
✦ ფუნქციები

ყველაფერი, რაც გჭირდებათ

ერთი პლატფორმა — ქონების სრული ციკლის მართვისთვის.

📦
ქონების სრული რეგისტრი
კომპიუტერი, მაგიდა, სკამი, პრინტერი — ყველა ობიექტი ინვენტარის ნომრით, სერიული ნომრით და ბარკოდით. სწრაფი ძებნა.
🔲
ბარკოდების გენერაცია და სკანირება
Code128 ბარკოდების ავტომატური გენერაცია. კამერით სკანირება. ბარკოდზე ეწერება უწყების სახელი.
📋
მიღება-ჩაბარების აქტები
ავტომატური დოკუმენტების გენერაცია. ბეჭდვა, ხელმოწერა, ატვირთვა. სრული ისტორია.
🏢
უწყებების მართვა
შექმენით უწყებები, მიანიჭეთ ადმინები. თითოეული უწყება ხედავს მხოლოდ საკუთარ ქონებას.
🔐
მრავალდონიანი წვდომა
მთავარი ადმინი ანიჭებს წვდომას. პაროლები დაცულია — ხელახლა ჩვენება მხოლოდ ნებართვით.
📊
ანგარიშები და სტატისტიკა
განყოფილების, კატეგორიის, პასუხისმგებელი პირის მიხედვით. CSV ექსპორტი.
🔧
სარემონტო განაცხადები
ობიექტი გაფუჭდა? დაარეგისტრირეთ განაცხადი, თვალყური ადევნეთ სტატუსს — გახსნილი / შეკეთებაში / დასრულებული.
🛡️
გარანტია და სადაზღვევო
ყოველი ობიექტის გარანტიის ვადა, სადაზღვევო პოლისი. ვადის ამოწურვამდე 30 დღით ადრე — ავტომატური შეხსენება.
📉
ამორტიზაციის კალკულატორი
ავტომატური ბალანსური ღირებულების გამოთვლა წრფივი მეთოდით. ჩამოწერის გეგმა — კატეგორიის, ვადის, ნარჩენი ღირებულების მიხედვით.
📲
QR კოდი + მობილური
QR კოდების გენერაცია ბარკოდთან ერთად. ტელეფონით სკანირება — მყისიერ ნახეთ ობიექტის სრული ისტორია.
🔔
შეტყობინებები და ალერტები
ელ-ფოსტით შეტყობინება: გარანტიის ამოწურვა, სარემონტო სტატუსის ცვლილება, ახალი მიღება-ჩაბარება. ყველაფერი ავტომატურად.
✦ პროცესი

როგორ მუშაობს

4 მარტივი ნაბიჯი

1
ობიექტის რეგისტრაცია
შეიყვანეთ მონაცემები. სისტემა ქმნის ბარკოდს უწყების სახელით.
2
ბარკოდის ბეჭდვა
ბეჭდავთ ეტიკეტს — ეწერება უწყება, სახელი, ნომერი. ადებთ ობიექტს.
3
მიღება-ჩაბარება
ბეჭდავთ აქტს, ხელს მოაწერინებთ, ასკანირებთ, ატვირთავთ PDF-ად.
4
კამერით სკანირება
ბარკოდს მიატანთ კამერასთან — მყისიერ გამოჩნდება ობიექტის სრული ინფორმაცია.
✦ ფასი

ერთი გეგმა — ყველაფერი შეუზღუდავად

ტექნიკური მხარდაჭერა, განახლებები და ყველა ფუნქცია ერთ ფასად.

ყოველთვიური
წლიური დაზოგეთ 17%
🌟 სრული პაკეტი
LOGINTECHSOL.GE
₾3,999/წელი
💰 ₾333/თვე — დაზოგეთ ₾789 წელიწადში
ყოველთვიური: ₾4,788/წელი
ყველა ზომის უწყებებისთვის — შეუზღუდავად
  • შეუზღუდავი ადმინები
  • შეუზღუდავი ობიექტები
  • ბარკოდების გენერაცია და სკანირება
  • მიღება-ჩაბარების დოკუმენტები
  • Excel იმპორტი/ექსპორტი
  • სრული დოკუმენტ-მართვა
  • ყველა ფუნქცია + ახალი მოდულები
  • პირადი მენეჯერი
  • ონ-საიტ ინსტალაცია
  • 24/7 მხარდაჭერა ქართულ ენაზე
✦ გამოხმაურებები

ჩვენი კლიენტები ამბობენ

"სისტემამ სრულად გარდაქმნა ჩვენი ინვენტარის მართვა. ბარკოდებით ყველა ობიექტის მიდევნება გაცილებით მარტივია."
გმ
გიორგი მხეიძე
IT სამსახური
"მიღება-ჩაბარების დოკუმენტები ავტომატურად იქმნება, ვბეჭდავთ, ხელს ვაწერინებთ და ვტვირთავთ. ადრე 2 საათი გვჭირდებოდა, ახლა — 15 წუთი."
ნბ
ნინო ბერიძე
ადმინისტრაციის უფროსი
"კამერით სკანირება განსაკუთრებით მოხერხებულია. ბარკოდს მივატანთ — მყისიერ ჩნდება ყველა ინფორმაცია."
დხ
დავით ხვედელიძე
ფინანსური კონტროლი
დაიწყეთ დღეს
რეგისტრაცია 2 წუთი სჭირდება. სრული მხარდაჭერა ქართულ ენაზე.
🏛️
LOGINTECHSOL.GE
სისტემაში შესვლა
🧪
სადემო ვერსია
სისტემის გაცნობა — დემო მომხმარებელი
შეიყვანეთ თქვენი მონაცემები
❌ მომხმარებელი ან პაროლი არასწორია
🔑 პაროლი დამავიწყდა
← მთავარ გვერდზე დაბრუნება
00:00:00
A
ძირითადი
მოდულები
ანგარიში
სულ ქონება
0
0 კატ.
📦
გამოყენებაში
0
ჩაბარებული
ბალანსური ღირებულება
₾0
სულ ბალანსი
💰
დაზიანებული
0
შეკეთება/ჩამოწერილი
⚠️
დოკუმენტები
0
0 შესყიდვა
📋
📊 კატეგორიის მიხედვით
👤 პასუხისმგებელი პირები
🕐 ბოლო ჩამატებული
ინვენტარის ნომერისახელისტატუსიპასუხისმგებელი პირიგანყოფილება/ოთახიღირებულება (₾)თარიღი
📦 ქონების სრული სია
📋 შაბლონი:
ინვენტარის ნომერიბარკოდისახელი / სერიულიკატეგორიაუწყებაგანყოფილება/ოთახიპასუხისმგებელი პირიღირებულება (₾)სტატუსიმოქმედება
📷 ბარკოდის სკანირება — ქონების აღწერა
📷 კამერა
📷
სკანირების დასაწყებად
დააჭირეთ ▶ სკანირება
📋 სკანირების შედეგი
🔲
ბარკოდი ჯერ არ სკანირებულა
📜 სკანირებულთა სია
სია ცარიელია
📋 მიღება-ჩაბარების დოკუმენტები
დოკუმენტის ნომერითარიღიობიექტებიგამცემიმიმღებიგანყოფილებასტატუსიფაილიმოქმედება
🛒 შესყიდვის დოკუმენტები
შესყიდვის ნომერითარიღიმომწოდებელიობიექტებირაოდენობაერთეულის ფასიჯამური ღირებულებასტატუსიფაილიმოქმედება
👤 პასუხისმგებელი პირები
📋 შაბლონი:ჩამოტვირთე შაბლონი, შეავსე და ატვირთე იმპორტისთვის
🏢 უწყებები
🏢 როგორ მუშაობს უწყებების სისტემა
1️⃣
სუპერ ადმინი ქმნის უწყებას
+ უწყების დამატება → სახელი, კოდი
2️⃣
ადმინი ეხლება უწყებას
🔑 ადმინები → + ადმინი → უწყება
3️⃣
ადმინი შედის სისტემაში
ხედავს მხოლოდ საკუთარ უწყებას
4️⃣
სუპერ ადმინი ხედავს ყველას
სულ ქონება, სტატუსი, ყველა უწყება
🔑 ადმინების მართვა
📖 როგორ მიანიჭოთ წვდომა
1
თანამშრომლის დამატება
სახელი, მომხმარებლის სახელი, პაროლი
2
წვდომის მინიჭება
გაუგზავნეთ მომხმარებლის სახელი და პაროლი
3
კოლეგა შედის
logintechsol.ge → შესვლა
4
მართვა
გამორთვა/ჩართვა/წაშლა ნებისმიერ დროს
🔐 პაროლის დაცვა: პაროლი ნაჩვენებია მხოლოდ 👁️ ღილაკის დაჭერისას.
სახელი გვარიმომხმარებლის სახელიპაროლიუწყებაროლიშექმნის თარიღისტატუსიმოქმედება
📈 ანგარიში
ბალანსური ღირებულება
₾0
💰
გამოყენებაში
0
დაზიანებული/ჩამოწერილი
0
⚠️
მიღება-ჩაბარების დოკუმენტი
0
📋
შესყიდვის დოკუმენტი
0
🛒
🏢 უწყების მიხედვით
🏛️ განყოფილების მიხედვით
📦 კატეგორიის მიხედვით
🔧 Supabase დიაგნოსტიკა
🌐 კავშირი
გასაშვებად დააჭირეთ ▶
🗄️ ცხრილები
გასაშვებად დააჭირეთ ▶
📊 მონაცემები Supabase-ში
გასაშვებად დააჭირეთ ▶
✍️ ჩაწერის ტესტი
გასაშვებად დააჭირეთ ▶
📋 სრული ლოგი
🗺️
ლოკაციების მართვა
შექმენით კორპუსები, სართულები და ოთახები. ყოველ ოთახს მიაბამთ ინვენტარს — ნახეთ სად ზის ყოველი ობიექტი. დააჭირეთ ლოკაციას მარჯვნივ — გამოვა იქ არსებული ქონების სრული სია.
🗺️ ლოკაციები
📦 ლოკაცია არ არის არჩეული
← მარცხნიდან აირჩიეთ ლოკაცია
📦
საწყობის მართვა
შექმენით ერთი ან რამდენიმე საწყობი. ნახეთ რა ობიექტები ზის საწყობში ამ დროისთვის. ობიექტის გამოტანისას სისტემა ავტომატურად ჩაწერს ისტორიაში — ვინ გამოიტანა, სად წავიდა, როდის.
📦 საწყობები
🔧
სარემონტო განაცხადები
ობიექტი გაფუჭდა? შექმენით სარემონტო განაცხადი, მიუთითეთ პრობლემა და პასუხისმგებელი. სტატუსი: გახსნილი → შეკეთებაში → დასრულებული. ყველა ხარჯი და ჩანაწერი ინახება ობიექტის ისტორიაში.
🛡️
გარანტია და სადაზღვევო
ყოველი ობიექტის გარანტიის ვადა და სადაზღვევო პოლისი. მწვანე — მოქმედია, ყვითელი — 30 დღეში იწურება, წითელი — ამოიწურა. დააჭირეთ ობიექტს გარანტიის ვადის სანახავად ან შესაცვლელად.
📜
ცვლილებების ჟურნალი
სრული ისტორია — ვინ შეცვალა, რა შეცვალა, როდის. ყოველი დამატება, რედაქტირება, წაშლა, სტატუსის ცვლილება — ყველაფერი ჩაწერილია. გამოიყენეთ ძებნა ან ფილტრი სასურველი ოპერაციის სწრაფად მოსაძებნად.
📋
პერიოდული ინვენტარიზაცია
შექმენით ინვენტარიზაციის სია — სისტემა ამოიღებს ყველა ობიექტს. ადმინი მიდის ადგილზე და ამოწმებს: ნაპოვნი / ვერ მოიძებნა / გადაადგილებული. სესიის დახურვისას გენერირდება ანგარიში.
📋 ინვენტარიზაციის სესიები
მასობრივი ოპერაციები
მონიშნეთ ერთდროულად რამდენიმე ობიექტი და შეასრულეთ ოპერაცია: სტატუსის შეცვლა, პასუხისმგებელი პირის მინიჭება, განყოფილებაში გადატანა, ჩამოწერა ან Excel-ში გამოტანა. ერთ წამში — ნაცვლად ასჯერ ცალ-ცალკე.
ინვენტარის ნომერისახელიკატეგორიასტატუსიუწყებაგანყოფ.პასუხისმგებელი
🔑
ლიცენზიების მართვა
პროგრამული ლიცენზიები, გასაღებები, ვადები. ნახეთ რამდენი ლიცენზია გამოიყენება რამდენიდან. ყვითელი — 30 დღეში იწურება, წითელი — ამოიწურა. გასაღების ნახვა — მხოლოდ ადმინს.
🔑 ლიცენზიები
დავალებები
ადმინმა დაავალოს სხვა ადმინს კონკრეტული ამოცანა — ვადით და პრიორიტეტით. სტატუსი: შესასრულებელი → შესრულებაში → შესრულებული. ყოველი ადმინი ხედავს თავის დავალებებს, ზედა ადმინი — ყველასას.
📄
PDF ანგარიშები
აირჩიეთ ანგარიშის ტიპი და დააჭირეთ გენერირებას. ბეჭდვა ან შენახვა PDF-ად ხდება ბრაუზერის ბეჭდვის ფუნქციით.
📦
ინვენტარის სრული ანგარიში
ყველა ობიექტი — ინვენტარის ნომერი, სახელი, კატეგორია, სტატუსი, ღირებულება, პასუხისმგებელი პირი. ფილტრი: უწყება, სტატუსი, კატეგორია.
🏢
უწყების ანგარიში
კონკრეტული უწყების ქონების სრული სია, სტატისტიკა — სულ ობიექტი, ბალანსური ღირებულება, კატეგორიების განაწილება.
📉
ამორტიზაციის ცხრილი
ყველა ობიექტის შეძენის ღირებულება, გამოყენების წლები, ამორტიზაცია და ნარჩენი ბალანსური ღირებულება. საბუღალტრო ჩამოწერისთვის.
🔧
სარემონტო ანგარიში
ყველა სარემონტო განაცხადი — ობიექტი, პრობლემა, სტატუსი, გახსნის/დასრულების თარიღი, ხარჯი. სულ ხარჯების სტატისტიკა.
🛡️
გარანტიის ანგარიში
ყველა ობიექტის გარანტიისა და სადაზღვევო ვადები. გამოყოფილია: ვადაგასული, 30 დღეში იწურება, მოქმედი.
📋
ინვენტარიზაციის ანგარიში
ინვენტარიზაციის სესიის შედეგები — ნაპოვნი, ვერ მოიძებნა, გადაადგილებული. პროცენტული სტატისტიკა.
1 / 1
და ვერ შესრულდება. function esc(s){ if(s==null)return ""; return String(s) .replace(/&/g,"&") .replace(//g,">") .replace(/"/g,""") .replace(/'/g,"'"); } function set(id,v){const e=document.getElementById(id);if(e)e.textContent=v} function myAssets(){return CU&&CU.agencyId?assets.filter(a=>a.agencyId===CU.agencyId):assets} function myPersons(){return CU&&CU.agencyId?persons.filter(p=>p.agencyId===CU.agencyId):persons} function agName(id){const ag=agencies.find(a=>a.id===id);return ag?ag.name:""} // SELECTS function popSel(id){const s=document.getElementById(id);if(!s)return;const v=s.value;s.innerHTML='';myPersons().forEach(p=>s.innerHTML+=``);s.value=v} function popAgSel(id){const s=document.getElementById(id);if(!s)return;s.innerHTML='';agencies.forEach(a=>s.innerHTML+=``)} function popPerDept(){const s=document.getElementById("perd");if(!s)return;const depts=[...new Set(assets.map(a=>a.dept).filter(Boolean))];const agDepts=agencies.map(a=>a.name);const allDepts=[...new Set([...depts,...agDepts])].sort();s.innerHTML=''+allDepts.map(d=>``).join("")+'';s.onchange=function(){if(this.value==="__custom__"){const inp=document.createElement("input");inp.className="inp";inp.id="perd";inp.placeholder="შეიყვანეთ განყოფილება";this.parentNode.replaceChild(inp,this)}}} function updFilters(){ const dp=document.getElementById("fdpt"),af=document.getElementById("fagf"); if(!dp||!af)return; const depts=[...new Set(myAssets().map(a=>a.dept).filter(Boolean))]; dp.innerHTML=''+depts.map(d=>``).join(""); af.innerHTML=''; agencies.forEach(a=>af.innerHTML+=``); } // STATS function renderStats(){ const list=myAssets(); const inuse=list.filter(a=>a.status==="გამოყენებაში").length; const dmg=list.filter(a=>a.status==="დაზიანებული"||a.status==="ჩამოწერილი").length; const val=list.reduce((s,a)=>s+a.value,0); const cats=[...new Set(list.map(a=>a.cat))].length; set("ss0",list.length);set("ss0s",cats+" კატ.");set("ss1",inuse); set("ss2","₾"+fmt(val));set("ss3",dmg);set("ss4",transfers.length);set("ss4s",procs.length+" შესყიდვა"); const m={};list.forEach(a=>{m[a.cat]=m[a.cat]||{c:0,v:0};m[a.cat].c++;m[a.cat].v+=a.value}); const sorted=Object.entries(m).sort((a,b)=>b[1].c-a[1].c); const mc=Math.max(...sorted.map(([,d])=>d.c),1); const cEl=document.getElementById("catChart"); cEl.innerHTML=sorted.map(([cat,d])=>`
${cat}
${d.c}ც.₾${d.v.toFixed(0)}
`).join("")||'
📦
'; const pd=myPersons().map(p=>{const a=list.filter(x=>x.personId===p.id);return{name:p.name,pos:p.pos,cnt:a.length,val:a.reduce((s,x)=>s+x.value,0)}}).sort((a,b)=>b.val-a.val); document.getElementById("perChart").innerHTML=pd.map(d=>`
👤 ${d.name}
${d.pos}
${d.cnt}ც.
₾${d.val.toFixed(0)}
`).join("")||'
👤
'; const sC={"გამოყენებაში":"bdg","საწყობში":"bdb","დაზიანებული":"bdo","ჩამოწერილი":"bdr"}; document.getElementById("recTb").innerHTML=myAssets().slice().reverse().slice(0,7).map(a=>{const p=persons.find(x=>x.id===a.personId);return`${esc(a.inv)}
${esc(a.name)}
${esc(a.cat)}
${esc(a.status)}${p?p.name:"—"}${esc(a.dept||"—")}${a.room?" / ოთ."+a.room:""}₾${a.value.toFixed(0)}${a.date||"—"}`}).join("")||'
📦
'; } // INVENTORY function renderInv(){ const q=(document.getElementById("fsrch")?.value||"").toLowerCase(); const fc=document.getElementById("fcat")?.value||""; const fs=document.getElementById("fst")?.value||""; const fd=document.getElementById("fdpt")?.value||""; const fa=document.getElementById("fagf")?.value||""; let list=myAssets().filter(a=>{ if(q&&!a.name.toLowerCase().includes(q)&&!a.inv.toLowerCase().includes(q)&&!a.barcode.toLowerCase().includes(q))return false; if(fc&&a.cat!==fc)return false; if(fs&&a.status!==fs)return false; if(fd&&a.dept!==fd)return false; if(fa&&a.agencyId!==fa)return false; return true; }); const sC={"გამოყენებაში":"bdg","საწყობში":"bdb","დაზიანებული":"bdo","ჩამოწერილი":"bdr"}; document.getElementById("invBody").innerHTML=list.map(a=>{const p=persons.find(x=>x.id===a.personId);const ag=agName(a.agencyId);return` ${esc(a.inv)} ${esc(a.barcode)}
${esc(a.name)}
${a.serial?`
SN: ${esc(a.serial)}
`:""} ${esc(a.cat)} ${ag?`${ag}`:"—"}
${esc(a.dept||"—")}
${a.room?`
ოთ. ${esc(a.room)}
`:""} ${p?`
${esc(p.name)}
${esc(p.pos)}
`:''} ₾${a.value.toFixed(2)} ${esc(a.status)}
`}).join("")||`
🔍
ვერ მოიძებნა
`; } function clearFilt(){["fsrch","fcat","fst","fdpt","fagf"].forEach(i=>{const e=document.getElementById(i);if(e)e.value=""});renderInv()} async function delA(id){if(!confirm("წაშლა?"))return;assets=assets.filter(a=>a.id!==id);await deleteA(id);renderInv();renderStats();toast("🗑️ წაშლილია")} let editAssetId=null; function editA(id){ const a=assets.find(x=>x.id===id);if(!a)return; editAssetId=id; openM("mAsset"); document.getElementById("an").value=a.name||""; document.getElementById("ac").value=a.cat||"💻 კომპიუტერი"; document.getElementById("aser").value=a.serial||""; document.getElementById("ainv").value=a.inv||""; document.getElementById("abc").value=a.barcode||""; document.getElementById("av").value=a.value||0; document.getElementById("adt").value=a.date||""; document.getElementById("ast").value=a.status||"საწყობში"; document.getElementById("arm").value=a.room||""; document.getElementById("adp").value=a.dept||""; document.getElementById("aag").value=a.agencyId||""; document.getElementById("aper").value=a.personId||""; document.getElementById("anote").value=a.note||""; if(a.barcode)prevBC(a.barcode); toggleStatusFields(); if(a.damageDesc)document.getElementById("admgDesc").value=a.damageDesc; if(a.invCheckDate)document.getElementById("ainvDate").value=a.invCheckDate; if(a.writeoffReason)document.getElementById("awoReason").value=a.writeoffReason; document.getElementById("mAsset").querySelector(".mtit").textContent="📦 ობიექტის რედაქტირება"; } // BC GEN function gCode128(){return"LTS"+String(Date.now()).slice(-10)} // SEQUENCE HELPER — გამოიანგარიშებს შემდეგ ხელმისაწვდომ ნომერს // (ცვლის ცუდ `array.length+1` ფორმულას, რომელიც წაშლის შემდეგ კონფლიქტს იწვევდა) function nextSeq(prefix,items,key,padLen){ const year=new Date().getFullYear(); const re=new RegExp("^"+prefix+"-"+year+"-(\\d+)$"); let max=0; for(const it of items){ const m=(it[key]||"").match(re); if(m){const n=parseInt(m[1],10);if(n>max)max=n} } return String(max+1).padStart(padLen,"0"); } function gInv(){document.getElementById("ainv").value="INV-"+new Date().getFullYear()+"-"+nextSeq("INV",assets,"inv",3)} function gBC(){const bc=gCode128();document.getElementById("abc").value=bc;prevBC(bc)} function prevBC(bc){const w=document.getElementById("abcPrev");if(!bc){w.style.display="none";return}try{JsBarcode("#abcSvg",bc,{format:"CODE128",width:2,height:50,displayValue:true,fontSize:10,margin:5});document.getElementById("abcNum").textContent=bc;const nameEl=document.getElementById("abcName");if(nameEl)nameEl.textContent=document.getElementById("an").value||"";w.style.display="block"}catch(e){w.style.display="none"}} // STATUS TOGGLE function toggleStatusFields(){ const st=document.getElementById("ast").value; document.getElementById("damageFields").style.display=st==="დაზიანებული"?"block":"none"; document.getElementById("writeoffFields").style.display=st==="ჩამოწერილი"?"block":"none"; } let assetPhotos=[null,null,null]; // FIX #19: ფოტოების კომპრესია → ფაილის ზომა ბაზაში დრამატულად მცირდება async function prevAssetPhoto(n,e){ const f=e.target.files[0];if(!f)return; // ჯერ კომპრესია (max 1200px, 80% quality), წინააღმდეგ შემთხვევაში ფაილის raw base64 — ფოლბექი let dataUrl; try{ if(f.type&&f.type.startsWith("image/")){ dataUrl=await _compressImage(f,1200,0.8); }else{ // არა-სურათი — როგორც-არის dataUrl=await new Promise((res,rej)=>{const r=new FileReader();r.onload=()=>res(r.result);r.onerror=rej;r.readAsDataURL(f)}); } }catch(err){ console.warn("[photo] compression failed, using original:",err.message); dataUrl=await new Promise((res,rej)=>{const r=new FileReader();r.onload=()=>res(r.result);r.onerror=rej;r.readAsDataURL(f)}); } assetPhotos[n-1]=dataUrl; document.getElementById("aphPrev"+n).innerHTML=``; } // SAVE ASSET async function saveAsset(){ const name=document.getElementById("an").value.trim(); if(!name){toast("⚠️ სახელი სავალდებულოა!","#dc2626");return} const bc=document.getElementById("abc").value||gCode128(); const inv=document.getElementById("ainv").value||("INV-"+Date.now()); // DUPLICATE CHECK — ინვ. ნომერი და ბარკოდი უნდა იყოს უნიკალური (გარდა იმ შემთხვევისა, თუ რედაქტირებაში ვართ) const dupInv=assets.find(x=>x.inv===inv&&x.id!==editAssetId); if(dupInv){toast("⚠️ ინვ. ნომერი "+inv+" უკვე არსებობს ("+dupInv.name+")","#dc2626");return} const dupBc=assets.find(x=>x.barcode===bc&&x.id!==editAssetId); if(dupBc){toast("⚠️ ბარკოდი "+bc+" უკვე არსებობს ("+dupBc.name+")","#dc2626");return} const agId=CU.agencyId||document.getElementById("aag").value||""; const status=document.getElementById("ast").value; const dmgDesc=status==="დაზიანებული"?(document.getElementById("admgDesc").value||""):""; const invDate=status==="ჩამოწერილი"?(document.getElementById("ainvDate").value||""):""; const woReason=status==="ჩამოწერილი"?(document.getElementById("awoReason").value||""):""; const photos=assetPhotos.filter(p=>p!==null); const a={id:"a"+Date.now(),name,cat:(document.getElementById("ac").value==="📦 სხვა"&&document.getElementById("acCustom").value.trim())?("📦 "+document.getElementById("acCustom").value.trim()):document.getElementById("ac").value,serial:document.getElementById("aser").value,inv,barcode:bc,value:parseFloat(document.getElementById("av").value)||0,date:document.getElementById("adt").value,status:status,dept:document.getElementById("adp").value,room:document.getElementById("arm").value,personId:document.getElementById("aper").value,agencyId:agId,note:document.getElementById("anote").value,damageDesc:dmgDesc,invCheckDate:invDate,writeoffReason:woReason,photos:photos,created:new Date().toISOString()}; if(editAssetId){a.id=editAssetId;const idx=assets.findIndex(x=>x.id===editAssetId);if(idx>=0){if(!photos.length&&assets[idx].photos)a.photos=assets[idx].photos;assets[idx]=a}editAssetId=null}else{assets.push(a)}await saveA();closeM("mAsset"); ["an","aser","ainv","abc","av","adp","arm","anote","admgDesc","ainvDate","awoReason"].forEach(i=>{const e=document.getElementById(i);if(e)e.value=""}); document.getElementById("abcPrev").style.display="none"; document.getElementById("damageFields").style.display="none"; document.getElementById("writeoffFields").style.display="none"; assetPhotos=[null,null,null]; [1,2,3].forEach(n=>document.getElementById("aphPrev"+n).innerHTML="📷"); updFilters();renderInv();renderStats();toast("✅ ობიექტი დამატებულია!","#059669"); } // VIEW ASSET function viewA(id){ const a=assets.find(x=>x.id===id);if(!a)return; const p=persons.find(x=>x.id===a.personId); const ag=agencies.find(x=>x.id===a.agencyId); document.getElementById("vAT").textContent="📦 "+a.name; document.getElementById("vAB").innerHTML=`
${[["ინვენტარის ნომერი",a.inv],["სერიული ნომერი",a.serial||"—"],["კატეგორია",a.cat],["სტატუსი",a.status],["ღირებულება","₾"+a.value.toFixed(2)],["შეძენის თარიღი",a.date||"—"],["განყოფილება",a.dept||"—"],["ოთახი",a.room||"—"],["უწყება",ag?ag.name:"—"],["ბარკოდი",a.barcode]].map(([l,v])=>`
${l}
${v}
`).join("")}
${p?`
👤 პასუხისმგებელი პირი
${esc(p.name)}
${esc(p.pos)} · ${esc(p.dept)}
`:""} ${a.damageDesc?`
⚠️ დაზიანების აღწერა
${esc(a.damageDesc)}
`:""} ${a.writeoffReason?`
❌ ჩამოწერის მიზეზი
${esc(a.writeoffReason)}
${a.invCheckDate?`
ინვენტარიზაციის თარიღი: ${a.invCheckDate}
`:""}
`:""} ${a.photos&&a.photos.length?`
${a.photos.map((ph,i)=>``).join("")}
🔍 დააჭირე ფოტოს გასადიდებლად (${a.photos.length} ფოტო)
`:""}
${esc(a.name)}
${esc(a.barcode)}
${ag?ag.name:""}
`; openM("mViewA"); setTimeout(()=>{try{JsBarcode("#vbcS",a.barcode,{format:"CODE128",width:2,height:62,displayValue:true,fontSize:10,margin:6})}catch(e){}},55); } function printBarcode(id){ const a=assets.find(x=>x.id===id);if(!a)return; const ag=agencies.find(x=>x.id===a.agencyId); const win=window.open("","_blank"); win.document.write(`ბარკოდი - ${esc(a.name)}