asr:/var/www/marketplace-sqlserver/marketplace-sqlserver/backend# pm2 logs marketplace --lines 20 [TAILING] Tailing last 20 lines for [marketplace] process (change the value with --lines option) /root/.pm2/logs/marketplace-out.log last 20 lines: 0|marketpl | 7,42,23,41,169,56,11,88,249,34,96,124,19,231,147,154,215,151,28,11,205,14,177,241,202,99,205,133,228,0,51,152,160,180,63,207,29,208,183,223,84,24,126,146,251,72,87,153,45,52,222,179,86,112,103,150,90,149,54,12,230,98,104,50,52,29,90,10,217,65,78,0,168,8,2,7,131,68,38,224,69,196,32,0,96,250,113,148,75,177,217,17,15,153,247,251,138,96,137,140,172,82,80,57,241,253,138,92,68,151,146,198,65,141,215,58,144,227,115,134,231,185,27,118,233,118,131,225,181,29,160,217,92,206,141,40,191,202,25,62,189,133,198,123,214,10,238,204,82,171,242,134,250,181,30,6,216,28,154,54,168,95,255,185,10,4,130,128,38,161,89,34,8,160,230,85,8,48,186,70,75,90,83,230,143,87,173,141,251,65,178,0,154,95,12,29,48,118,66,14,100,10,54,61,54,53,60,12,78,195,207,69,100,103,116,223,156,11,182,220,199,178,218,108,161,241,158,181,130,59,179,212,234,182,193,28,60,143,97,79,133,2,204,179,212,135,1,35,42,163,46,59,223,132,0,27,98,92,192,34,16,112,0,208,142,186,158,235,190,178,196,215,144,232,157,199,220,106,112,128,77,164,70,135,56,45,55,219,153,125,50,47,226,226,14,119,181,222,66,227,61,107,5,119,102,169,214,205,110,4,3,12,54,25,198,155,58,116,224,224,217,168,159,231,34,43,88,102,103,5,70,90,16,36,32,96,205,47,103,199,173,4,49,155,32,128,212,240,145,193,53,154,247,105,96,250,78,163,139,201,161,73,208,106,23,213,151,103,11,141,247,172,21,220,153,165,90,183,166,183,225,131,135,22,163,246,158,4,16,76,26,51,114,212,84,100,4,83,1,130,169,227,199,142,159,6,16,204,133,129,85,203,212,208,141,201,173,245,159,143,159,163,199,2,46,83,71,12,25,70,248,76,37,136,8,164,213,161,78,255,33,183,208,120,207,86,166,205,255,3,92,188,195,160,140,5,29,122,0,0,0,0,73,69,78,68,174,66,96,130]},"Statue":false,"Location":null,"Project":null,"AgentID":null,"Hafez":null,"Type":true,"BranchId":1} 0|marketpl | 📋 الجداول: BackItemHeader, card_numbers, Sale_Invoice, Expenses, sysdiagrams, stock, Cont_TblMoasfatCabina, Test, Cont_TblMoasfatMakina, CashClose, rec_invoce2, RealQuantatyOfSale, card_numbers2, Cont_TblMoasfatDoors, TakeInvoice, classes, Cont_TblTarkeep, rec_invoce, Cont_TblDoes, copy, ExpsType, Cont_TblDofaat, Recept_Of_Items, customer, ACC, AgentFlow, SalesType, Cont_TblHeader, Adds, SalesReport, Information, Cont_FirstDataPreview, Item_Info, POS_Users, TaxesReports, DeletedInvoice, Branch, BackItems, TopClass, TranseTottal, Item_Price, NewEdit, provider, Item_Barcode, cust_debit, rec_cust, TblSerials, ReceptOfItemDetails, Cont_Agent, Per_Forms, SaleReportDtl, Cont_TblSekakBuild, Per_ClassPermession, FinalClass, BackDistroy, Real_Quantaty, Per_ClassFrm, BackSales, CustomerCalc, Hr_FingerLog, customerLink, Hr_DeviceInfo, Per_FormPermessions, ExpensesCustomer, Part_Tottal, Delevery, Role_Details, Tblinfo, TranseDtl, Con_TblContIncrease, StdData, Puch_Invoice, Sale_Invoice_Details, SaveMoney, prov_debit, SaveMoneyType, CheequeFollow, Plumber 0|marketpl | 📋 الجداول: BackItemHeader, card_numbers, Sale_Invoice, Expenses, sysdiagrams, stock, Cont_TblMoasfatCabina, Test, Cont_TblMoasfatMakina, CashClose, rec_invoce2, RealQuantatyOfSale, card_numbers2, Cont_TblMoasfatDoors, TakeInvoice, classes, Cont_TblTarkeep, rec_invoce, Cont_TblDoes, copy, ExpsType, Cont_TblDofaat, Recept_Of_Items, customer, ACC, AgentFlow, SalesType, Cont_TblHeader, Adds, SalesReport, Information, Cont_FirstDataPreview, Item_Info, POS_Users, TaxesReports, DeletedInvoice, Branch, BackItems, TopClass, TranseTottal, Item_Price, NewEdit, provider, Item_Barcode, cust_debit, rec_cust, TblSerials, ReceptOfItemDetails, Cont_Agent, Per_Forms, SaleReportDtl, Cont_TblSekakBuild, Per_ClassPermession, FinalClass, BackDistroy, Real_Quantaty, Per_ClassFrm, BackSales, CustomerCalc, Hr_FingerLog, customerLink, Hr_DeviceInfo, Per_FormPermessions, ExpensesCustomer, Part_Tottal, Delevery, Role_Details, Tblinfo, TranseDtl, Con_TblContIncrease, StdData, Puch_Invoice, Sale_Invoice_Details, SaveMoney, prov_debit, SaveMoneyType, CheequeFollow, Plumber 0|marketpl | 0|marketpl | > marketplace-backend@1.0.0 start 0|marketpl | > node src/index.js 0|marketpl | 0|marketpl | 0|marketpl | > marketplace-backend@1.0.0 start 0|marketpl | > node src/index.js 0|marketpl | /root/.pm2/logs/marketplace-error.log last 20 lines: 0|marketpl | at Module._compile (node:internal/modules/cjs/loader:1364:14) 0|marketpl | 0|marketpl | Node.js v18.20.8 0|marketpl | /var/www/marketplace-sqlserver/marketplace-sqlserver/backend/src/routes/admin.js:356 0|marketpl | 0|marketpl | 0|marketpl | 0|marketpl | SyntaxError: Unexpected end of input 0|marketpl | at internalCompileFunction (node:internal/vm:76:18) 0|marketpl | at wrapSafe (node:internal/modules/cjs/loader:1283:20) 0|marketpl | at Module._compile (node:internal/modules/cjs/loader:1328:27) 0|marketpl | at Module._extensions..js (node:internal/modules/cjs/loader:1422:10) 0|marketpl | at Module.load (node:internal/modules/cjs/loader:1203:32) 0|marketpl | at Module._load (node:internal/modules/cjs/loader:1019:12) 0|marketpl | at Module.require (node:internal/modules/cjs/loader:1231:19) 0|marketpl | at require (node:internal/modules/helpers:177:18) 0|marketpl | at Object. (/var/www/marketplace-sqlserver/marketplace-sqlserver/backend/src/index.js:33:29) 0|marketpl | at Module._compile (node:internal/modules/cjs/loader:1364:14) 0|marketpl | 0|marketpl | Node.js v18.20.8 0|marketplace | > marketplace-backend@1.0.0 start 0|marketplace | > node src/index.js 0|marketplace | /var/www/marketplace-sqlserver/marketplace-sqlserver/backend/src/routes/admin.js:356 0|marketplace | SyntaxError: Unexpected end of input 0|marketplace | at internalCompileFunction (node:internal/vm:76:18) 0|marketplace | at wrapSafe (node:internal/modules/cjs/loader:1283:20) 0|marketplace | at Module._compile (node:internal/modules/cjs/loader:1328:27) 0|marketplace | at Module._extensions..js (node:internal/modules/cjs/loader:1422:10) 0|marketplace | at Module.load (node:internal/modules/cjs/loader:1203:32) 0|marketplace | at Module._load (node:internal/modules/cjs/loader:1019:12) 0|marketplace | at Module.require (node:internal/modules/cjs/loader:1231:19) 0|marketplace | at require (node:internal/modules/helpers:177:18) 0|marketplace | at Object. (/var/www/marketplace-sqlserver/marketplace-sqlserver/backend/src/index.js:33:29) 0|marketplace | at Module._compile (node:internal/modules/cjs/loader:1364:14) 0|marketplace | Node.js v18.20.8 0|marketplace | > marketplace-backend@1.0.0 start 0|marketplace | > node src/index.js 0|marketplace | /var/www/marketplace-sqlserver/marketplace-sqlserver/backend/src/routes/admin.js:356 0|marketplace | SyntaxError: Unexpected end of input 0|marketplace | at internalCompileFunction (node:internal/vm:76:18) 0|marketplace | at wrapSafe (node:internal/modules/cjs/loader:1283:20) 0|marketplace | at Module._compile (node:internal/modules/cjs/loader:1328:27) 0|marketplace | at Module._extensions..js (node:internal/modules/cjs/loader:1422:10) 0|marketplace | at Module.load (node:internal/modules/cjs/loader:1203:32) 0|marketplace | at Module._load (node:internal/modules/cjs/loader:1019:12) 0|marketplace | at Module.require (node:internal/modules/cjs/loader:1231:19) 0|marketplace | at require (node:internal/modules/helpers:177:18) 0|marketplace | at Object. (/var/www/marketplace-sqlserver/marketplace-sqlserver/backend/src/index.js:33:29) 0|marketplace | at Module._compile (node:internal/modules/cjs/loader:1364:14) 0|marketplace | Node.js v18.20.8 0|marketplace | > marketplace-backend@1.0.0 start 0|marketplace | > node src/index.js 0|marketplace | /var/www/marketplace-sqlserver/marketplace-sqlserver/backend/src/routes/admin.js:356 0|marketplace | SyntaxError: Unexpected end of input 0|marketplace | at internalCompileFunction (node:internal/vm:76:18) 0|marketplace | at wrapSafe (node:internal/modules/cjs/loader:1283:20) 0|marketplace | at Module._compile (node:internal/modules/cjs/loader:1328:27) 0|marketplace | at Module._extensions..js (node:internal/modules/cjs/loader:1422:10) 0|marketplace | at Module.load (node:internal/modules/cjs/loader:1203:32) 0|marketplace | at Module._load (node:internal/modules/cjs/loader:1019:12) 0|marketplace | at Module.require (node:internal/modules/cjs/loader:1231:19) 0|marketplace | at require (node:internal/modules/helpers:177:18) 0|marketplace | at Object. (/var/www/marketplace-sqlserver/marketplace-sqlserver/backend/src/index.js:33:29) 0|marketplace | at Module._compile (node:internal/modules/cjs/loader:1364:14) 0|marketplace | Node.js v18.20.8 0|marketplace | > marketplace-backend@1.0.0 start 0|marketplace | > node src/index.js 0|marketplace | /var/www/marketplace-sqlserver/marketplace-sqlserver/backend/src/routes/admin.js:356 0|marketplace | SyntaxError: Unexpected end of input 0|marketplace | at internalCompileFunction (node:internal/vm:76:18) 0|marketplace | at wrapSafe (node:internal/modules/cjs/loader:1283:20) 0|marketplace | at Module._compile (node:internal/modules/cjs/loader:1328:27) 0|marketplace | at Module._extensions..js (node:internal/modules/cjs/loader:1422:10) 0|marketplace | at Module.load (node:internal/modules/cjs/loader:1203:32) 0|marketplace | at Module._load (node:internal/modules/cjs/loader:1019:12) 0|marketplace | at Module.require (node:internal/modules/cjs/loader:1231:19) 0|marketplace | at require (node:internal/modules/helpers:177:18) 0|marketplace | at Object. (/var/www/marketplace-sqlserver/marketplace-sqlserver/backend/src/index.js:33:29) 0|marketplace | at Module._compile (node:internal/modules/cjs/loader:1364:14) 0|marketplace | Node.js v18.20.8 0|marketplace | > marketplace-backend@1.0.0 start 0|marketplace | > node src/index.js 0|marketplace | /var/www/marketplace-sqlserver/marketplace-sqlserver/backend/src/routes/admin.js:356 0|marketplace | SyntaxError: Unexpected end of input 0|marketplace | at internalCompileFunction (node:internal/vm:76:18) 0|marketplace | at wrapSafe (node:internal/modules/cjs/loader:1283:20) 0|marketplace | at Module._compile (node:internal/modules/cjs/loader:1328:27) 0|marketplace | at Module._extensions..js (node:internal/modules/cjs/loader:1422:10) 0|marketplace | at Module.load (node:internal/modules/cjs/loader:1203:32) 0|marketplace | at Module._load (node:internal/modules/cjs/loader:1019:12) 0|marketplace | at Module.require (node:internal/modules/cjs/loader:1231:19) 0|marketplace | at require (node:internal/modules/helpers:177:18) 0|marketplace | at Object. (/var/www/marketplace-sqlserver/marketplace-sqlserver/backend/src/index.js:33:29) 0|marketplace | at Module._compile (node:internal/modules/cjs/loader:1364:14) 0|marketplace | Node.js v18.20.8 0|marketplace | > marketplace-backend@1.0.0 start 0|marketplace | > node src/index.js 0|marketplace | /var/www/marketplace-sqlserver/marketplace-sqlserver/backend/src/routes/admin.js:356 0|marketplace | SyntaxError: Unexpected end of input 0|marketplace | at internalCompileFunction (node:internal/vm:76:18) 0|marketplace | at wrapSafe (node:internal/modules/cjs/loader:1283:20) 0|marketplace | at Module._compile (node:internal/modules/cjs/loader:1328:27) 0|marketplace | at Module._extensions..js (node:internal/modules/cjs/loader:1422:10) 0|marketplace | at Module.load (node:internal/modules/cjs/loader:1203:32) 0|marketplace | at Module._load (node:internal/modules/cjs/loader:1019:12) 0|marketplace | at Module.require (node:internal/modules/cjs/loader:1231:19) 0|marketplace | at require (node:internal/modules/helpers:177:18) 0|marketplace | at Object. (/var/www/marketplace-sqlserver/marketplace-sqlserver/backend/src/index.js:33:29) 0|marketplace | at Module._compile (node:internal/modules/cjs/loader:1364:14) 0|marketplace | Node.js v18.20.8 0|marketplace | > marketplace-backend@1.0.0 start 0|marketplace | > node src/index.js 0|marketplace | /var/www/marketplace-sqlserver/marketplace-sqlserver/backend/src/routes/admin.js:356 0|marketplace | SyntaxError: Unexpected end of input 0|marketplace | at internalCompileFunction (node:internal/vm:76:18) 0|marketplace | at wrapSafe (node:internal/modules/cjs/loader:1283:20) 0|marketplace | at Module._compile (node:internal/modules/cjs/loader:1328:27) 0|marketplace | at Module._extensions..js (node:internal/modules/cjs/loader:1422:10) 0|marketplace | at Module.load (node:internal/modules/cjs/loader:1203:32) 0|marketplace | at Module._load (node:internal/modules/cjs/loader:1019:12) 0|marketplace | at Module.require (node:internal/modules/cjs/loader:1231:19) 0|marketplace | at require (node:internal/modules/helpers:177:18) 0|marketplace | at Object. (/var/www/marketplace-sqlserver/marketplace-sqlserver/backend/src/index.js:33:29) 0|marketplace | at Module._compile (node:internal/modules/cjs/loader:1364:14) 0|marketplace | Node.js v18.20.8 0|marketplace | > marketplace-backend@1.0.0 start 0|marketplace | > node src/index.js 0|marketplace | /var/www/marketplace-sqlserver/marketplace-sqlserver/backend/src/routes/admin.js:356 0|marketplace | SyntaxError: Unexpected end of input 0|marketplace | at internalCompileFunction (node:internal/vm:76:18) 0|marketplace | at wrapSafe (node:internal/modules/cjs/loader:1283:20) 0|marketplace | at Module._compile (node:internal/modules/cjs/loader:1328:27) 0|marketplace | at Module._extensions..js (node:internal/modules/cjs/loader:1422:10) 0|marketplace | at Module.load (node:internal/modules/cjs/loader:1203:32) 0|marketplace | at Module._load (node:internal/modules/cjs/loader:1019:12) 0|marketplace | at Module.require (node:internal/modules/cjs/loader:1231:19) 0|marketplace | at require (node:internal/modules/helpers:177:18) 0|marketplace | at Object. (/var/www/marketplace-sqlserver/marketplace-sqlserver/backend/src/index.js:33:29) 0|marketplace | at Module._compile (node:internal/modules/cjs/loader:1364:14) 0|marketplace | Node.js v18.20.8 0|marketplace | > marketplace-backend@1.0.0 start 0|marketplace | > node src/index.js 0|marketplace | /var/www/marketplace-sqlserver/marketplace-sqlserver/backend/src/routes/admin.js:356 0|marketplace | SyntaxError: Unexpected end of input 0|marketplace | at internalCompileFunction (node:internal/vm:76:18) 0|marketplace | at wrapSafe (node:internal/modules/cjs/loader:1283:20) 0|marketplace | at Module._compile (node:internal/modules/cjs/loader:1328:27) 0|marketplace | at Module._extensions..js (node:internal/modules/cjs/loader:1422:10) 0|marketplace | at Module.load (node:internal/modules/cjs/loader:1203:32) 0|marketplace | at Module._load (node:internal/modules/cjs/loader:1019:12) 0|marketplace | at Module.require (node:internal/modules/cjs/loader:1231:19) 0|marketplace | at require (node:internal/modules/helpers:177:18) 0|marketplace | at Object. (/var/www/marketplace-sqlserver/marketplace-sqlserver/backend/src/index.js:33:29) 0|marketplace | at Module._compile (node:internal/modules/cjs/loader:1364:14) 0|marketplace | Node.js v18.20.8 0|marketplace | > marketplace-backend@1.0.0 start 0|marketplace | > node src/index.js 0|marketplace | /var/www/marketplace-sqlserver/marketplace-sqlserver/backend/src/routes/admin.js:356 0|marketplace | SyntaxError: Unexpected end of input 0|marketplace | at internalCompileFunction (node:internal/vm:76:18) 0|marketplace | at wrapSafe (node:internal/modules/cjs/loader:1283:20) 0|marketplace | at Module._compile (node:internal/modules/cjs/loader:1328:27) 0|marketplace | at Module._extensions..js (node:internal/modules/cjs/loader:1422:10) 0|marketplace | at Module.load (node:internal/modules/cjs/loader:1203:32) 0|marketplace | at Module._load (node:internal/modules/cjs/loader:1019:12) 0|marketplace | at Module.require (node:internal/modules/cjs/loader:1231:19) 0|marketplace | at require (node:internal/modules/helpers:177:18) 0|marketplace | at Object. (/var/www/marketplace-sqlserver/marketplace-sqlserver/backend/src/index.js:33:29) 0|marketplace | at Module._compile (node:internal/modules/cjs/loader:1364:14) 0|marketplace | Node.js v18.20.8 0|marketplace | > marketplace-backend@1.0.0 start 0|marketplace | > node src/index.js 0|marketplace | /var/www/marketplace-sqlserver/marketplace-sqlserver/backend/src/routes/admin.js:356 0|marketplace | SyntaxError: Unexpected end of input 0|marketplace | at internalCompileFunction (node:internal/vm:76:18) 0|marketplace | at wrapSafe (node:internal/modules/cjs/loader:1283:20) 0|marketplace | at Module._compile (node:internal/modules/cjs/loader:1328:27) 0|marketplace | at Module._extensions..js (node:internal/modules/cjs/loader:1422:10) 0|marketplace | at Module.load (node:internal/modules/cjs/loader:1203:32) 0|marketplace | at Module._load (node:internal/modules/cjs/loader:1019:12) 0|marketplace | at Module.require (node:internal/modules/cjs/loader:1231:19) 0|marketplace | at require (node:internal/modules/helpers:177:18) 0|marketplace | at Object. (/var/www/marketplace-sqlserver/marketplace-sqlserver/backend/src/index.js:33:29) 0|marketplace | at Module._compile (node:internal/modules/cjs/loader:1364:14) 0|marketplace | Node.js v18.20.8 0|marketplace | > marketplace-backend@1.0.0 start 0|marketplace | > node src/index.js 0|marketplace | /var/www/marketplace-sqlserver/marketplace-sqlserver/backend/src/routes/admin.js:356 0|marketplace | SyntaxError: Unexpected end of input 0|marketplace | at internalCompileFunction (node:internal/vm:76:18) 0|marketplace | at wrapSafe (node:internal/modules/cjs/loader:1283:20) 0|marketplace | at Module._compile (node:internal/modules/cjs/loader:1328:27) 0|marketplace | at Module._extensions..js (node:internal/modules/cjs/loader:1422:10) 0|marketplace | at Module.load (node:internal/modules/cjs/loader:1203:32) 0|marketplace | at Module._load (node:internal/modules/cjs/loader:1019:12) 0|marketplace | at Module.require (node:internal/modules/cjs/loader:1231:19) 0|marketplace | at require (node:internal/modules/helpers:177:18) 0|marketplace | at Object. (/var/www/marketplace-sqlserver/marketplace-sqlserver/backend/src/index.js:33:29) 0|marketplace | at Module._compile (node:internal/modules/cjs/loader:1364:14) 0|marketplace | Node.js v18.20.8 0|marketplace | > marketplace-backend@1.0.0 start 0|marketplace | > node src/index.js 0|marketplace | /var/www/marketplace-sqlserver/marketplace-sqlserver/backend/src/routes/admin.js:356 0|marketplace | SyntaxError: Unexpected end of input 0|marketplace | at internalCompileFunction (node:internal/vm:76:18) 0|marketplace | at wrapSafe (node:internal/modules/cjs/loader:1283:20) 0|marketplace | at Module._compile (node:internal/modules/cjs/loader:1328:27) 0|marketplace | at Module._extensions..js (node:internal/modules/cjs/loader:1422:10) 0|marketplace | at Module.load (node:internal/modules/cjs/loader:1203:32) 0|marketplace | at Module._load (node:internal/modules/cjs/loader:1019:12) 0|marketplace | at Module.require (node:internal/modules/cjs/loader:1231:19) 0|marketplace | at require (node:internal/modules/helpers:177:18) 0|marketplace | at Object. (/var/www/marketplace-sqlserver/marketplace-sqlserver/backend/src/index.js:33:29) 0|marketplace | at Module._compile (node:internal/modules/cjs/loader:1364:14) 0|marketplace | Node.js v18.20.8 0|marketplace | > marketplace-backend@1.0.0 start 0|marketplace | > node src/index.js 0|marketplace | /var/www/marketplace-sqlserver/marketplace-sqlserver/backend/src/routes/admin.js:356 0|marketplace | SyntaxError: Unexpected end of input 0|marketplace | at internalCompileFunction (node:internal/vm:76:18) 0|marketplace | at wrapSafe (node:internal/modules/cjs/loader:1283:20) 0|marketplace | at Module._compile (node:internal/modules/cjs/loader:1328:27) 0|marketplace | at Module._extensions..js (node:internal/modules/cjs/loader:1422:10) 0|marketplace | at Module.load (node:internal/modules/cjs/loader:1203:32) 0|marketplace | at Module._load (node:internal/modules/cjs/loader:1019:12) 0|marketplace | at Module.require (node:internal/modules/cjs/loader:1231:19) 0|marketplace | at require (node:internal/modules/helpers:177:18) 0|marketplace | at Object. (/var/www/marketplace-sqlserver/marketplace-sqlserver/backend/src/index.js:33:29) 0|marketplace | at Module._compile (node:internal/modules/cjs/loader:1364:14) 0|marketplace | Node.js v18.20.8 0|marketplace | > marketplace-backend@1.0.0 start 0|marketplace | > node src/index.js ^C root@smasr:/var/www/marketplace-sqlserver/marketplace-sqlserver/backend# headers: {'Authorization': 'Bearer ' + token} }); if (!res.ok) { if (res.status === 401 || res.status === 403) { logout(); return; } throw new Error('فشل تحميل الإحصائيات'); } const stats = await res.json(); if(document.getElementById('stat2-total')) document.getElementById('stat2-total').textContent = stats.totalTenants || 0; if(document.getElementById('stat2-active')) document.getElementById('stat2-active').textContent = stats.activeTenants || 0; if(document.getElementById('stat2-subs')) document.getElementById('stat2-subs').textContent = stats.activeSubscriptions || 0; if(document.getElementById('stat2-orders')) document.getElementById('stat2-orders').textContent = stats.totalOrders || 0; // تغيير ID الإيرادات ليتطابق مع الـ HTML if(document.getElementById('stat2-sales')) document.getElementById('stat2-sales').textContent = (stats.totalSales || 0).toLocaleString() + ' $'; } catch (e) { console.error(e); } } function renderTable() { const tbody = document.getElementById('users-table'); if (!tenants.length) { tbody.innerHTML = 'لا توجد متاجر بعد'; return; } const filter = document.getElementById('statusFilter').value; const now = new Date(); let list = tenants; if (filter === 'expired') { list = tenants.filter(u => new Date(u.EndsAt) < now); } else if (filter === 'active') { list = tenants.filter(u => new Date(u.EndsAt) >= now); } tbody.innerHTML = list.map((u, i) => `
${u.DisplayName ? u.DisplayName[0] : 'م'}
${u.DisplayName || 'بدون اسم'}
المالك: ${u.OwnerName || 'غير محدد'}
${u.DbName || ''}
user: ${u.DbUser || ''}
${u.DbServer || ''}
port: ${u.DbPort || 1433}
${u.IsActive ? 'نشط' : 'معطل'} ${u.SubStatus === 'active' ? u.SubscriptionPlan : 'منتهي'} ${u.EndsAt ? new Date(u.EndsAt).toLocaleDateString('ar-EG') : 'N/A'}
`).join(''); if(document.getElementById('stat-total')) document.getElementById('stat-total').textContent = tenants.length; if(document.getElementById('stat-active')) document.getElementById('stat-active').textContent = tenants.filter(u => u.IsActive && u.SubStatus === 'active').length; if(document.getElementById('stat-inactive')) document.getElementById('stat-inactive').textContent = tenants.filter(u => !u.IsActive || u.SubStatus !== 'active').length; // تحديث إجمالي الإيرادات المتوقعة if(document.getElementById('stat2-sales') && tenants.length > 0) { const totalExpected = tenants.filter(u => u.SubStatus === 'active').reduce((sum, u) => sum + (u.Price || 0), 0); document.getElementById('stat2-sales').textContent = totalExpected.toLocaleString() + ' $'; } } async function addTenant() { const data = { slug: document.getElementById('newSlug').value, storeCode: document.getElementById('newStoreCode').value, displayName: document.getElementById('newDisplayName').value, ownerName: document.getElementById('newOwnerName').value, email: document.getElementById('newEmail').value, dbServer: document.getElementById('newDbServer').value, dbPort: parseInt(document.getElementById('newDbPort').value) || 1433, dbName: document.getElementById('newDbName').value, dbUser: document.getElementById('newDbUser').value, dbPassword: document.getElementById('newDbPassword').value, // Only send if changed or new plan: 'basic' }; const errorEl = document.getElementById('addError'); if (!data.slug || !data.displayName || !data.dbServer || !data.dbName) { errorEl.textContent = 'يرجى ملء الحقول المطلوبة'; errorEl.classList.add('show'); return; } try { const res = await fetch(API_URL + '/admin/tenants', { method: 'POST', headers: { 'Content-Type': 'application/json', 'Authorization': 'Bearer ' + token }, body: JSON.stringify(data) }); const result = await res.json(); if (!res.ok) throw new Error(result.error || 'فشل إضافة المتجر'); showNotif('تم إضافة المتجر بنجاح'); switchTab('users'); } catch (e) { errorEl.textContent = e.message; errorEl.classList.add('show'); } } async function testNewConnection() { const server = document.getElementById('newDbServer').value.trim(); const dbname = document.getElementById('newDbName').value.trim(); const dbuser = document.getElementById('newDbUser').value.trim(); const dbpass = document.getElementById('newDbPassword').value.trim(); const port = document.getElementById('newDbPort').value.trim(); const el = document.getElementById('test-result'); if (!server || !dbname) { el.className = 'test-result fail'; el.textContent = '❌ أدخل عنوان السيرفر واسم قاعدة البيانات أولاً'; return; } el.className = 'test-result'; el.textContent = '⏳ جاري اختبار الاتصال...'; el.style.display = 'block'; try { const res = await fetch(API_URL + '/admin/test-connection', { method: 'POST', headers: { 'Content-Type': 'application/json', 'Authorization': 'Bearer ' + token }, body: JSON.stringify({ server, port: parseInt(port) || 1433, dbName: dbname, dbUser: dbuser, dbPassword: dbpass }) }); const result = await res.json(); el.className = 'test-result ' + (result.success ? 'ok' : 'fail'); if (result.success) { el.textContent = '✓ الاتصال ناجح'; if (result.users && result.users.length > 0) { showUsersModal(result.users); } } else { el.textContent = `✗ فشل الاتصال: ${result.message}`; } } catch (e) { el.className = 'test-result fail'; el.textContent = `✗ خطأ في الاتصال: ${e.message}`; } } async function deleteTenant(id) { if (!confirm('هل تريد حذف هذا المتجر؟')) return; try { const res = await fetch(API_URL + '/admin/tenants/' + id, { method: 'DELETE', headers: {'Authorization': 'Bearer ' + token} }); if (!res.ok) { if (res.status === 401 || res.status === 403) { logout(); return; } throw new Error('فشل الحذف'); } loadTenants(); } catch (e) { showNotif(e.message, true); } } function showUsersModal(users) { const list = document.getElementById('userList'); list.innerHTML = users.map(u => `
${u.fullname || u.username}
@${u.username} - ${u.role}
`).join(''); document.getElementById('usersModal').classList.add('open'); } function closeUsersModal() { document.getElementById('usersModal').classList.remove('open'); } function selectUser(username, fullname, role) { closeUsersModal(); document.getElementById('newOwnerName').value = fullname; document.getElementById('newEmail').value = username + '@example.com'; } function editTenant(id) { const u = tenants.find(x => x.Id === id); if (!u) return; editTenantId = id; document.getElementById('newSlug').value = u.Slug || ''; // Slug is usually immutable document.getElementById('newStoreCode').value = u.StoreCode || ''; document.getElementById('newDisplayName').value = u.DisplayName || ''; document.getElementById('newOwnerName').value = u.OwnerName || ''; document.getElementById('newEmail').value = u.Email || ''; // Password is not retrieved for security reasons, user must re-enter if changing document.getElementById('newDbServer').value = u.DbServer || ''; document.getElementById('newDbPort').value = u.DbPort || 1433; document.getElementById('newDbName').value = u.DbName || ''; document.getElementById('newDbUser').value = u.DbUser || ''; document.getElementById('newDbPassword').value = u.DbPassword || ''; document.getElementById('saveBtn').textContent = 'تحديث المتجر'; document.getElementById('cancelBtn').style.display = 'inline-flex'; document.getElementById('addError').classList.remove('show'); // Clear previous errors switchTab('add'); } async function toggleTenantStatus(id, currentStatus) { try { const res = await fetch(`${API_URL}/admin/tenants/${id}`, { method: 'PUT', headers: { 'Content-Type': 'application/json', 'Authorization': 'Bearer ' + token }, body: JSON.stringify({ isActive: currentStatus ? 0 : 1 }) }); if (!res.ok) throw new Error('فشل تحديث حالة المتجر'); showNotif('تم تحديث حالة المتجر بنجاح'); loadTenants(); } catch (e) { showNotif(e.message, true); } } function cancelEdit() { editTenantId = null; document.getElementById('newSlug').value = ''; document.getElementById('newStoreCode').value = ''; document.getElementById('newDisplayName').value = ''; document.getElementById('newOwnerName').value = ''; document.getElementById('newEmail').value = ''; document.getElementById('newDbServer').value = ''; document.getElementById('newDbPort').value = '1433'; document.getElementById('newDbName').value = ''; document.getElementById('newDbUser').value = ''; document.getElementById('newDbPassword').value = ''; document.getElementById('saveBtn').textContent = 'حفظ المتجر'; document.getElementById('cancelBtn').style.display = 'none'; document.getElementById('addError').classList.remove('show'); document.getElementById('test-result').style.display = 'none'; } // This function now handles both Add and Update async function addTenant() { const data = { slug: document.getElementById('newSlug').value, storeCode: document.getElementById('newStoreCode').value, displayName: document.getElementById('newDisplayName').value, ownerName: document.getElementById('newOwnerName').value, // This is for the platform admin, not tenant user email: document.getElementById('newEmail').value, dbServer: document.getElementById('newDbServer').value, dbPort: parseInt(document.getElementById('newDbPort').value) || 1433, dbName: document.getElementById('newDbName').value, dbUser: document.getElementById('newDbUser').value, dbPassword: document.getElementById('newDbPassword').value, plan: 'basic' }; // Password for the tenant's admin user is not handled here, it's usually set by the tenant themselves or a default. const errorEl = document.getElementById('addError'); if (!data.slug || !data.displayName || !data.dbServer || !data.dbName) { errorEl.textContent = 'يرجى ملء الحقول المطلوبة'; errorEl.classList.add('show'); return; } try { let res; if (editTenantId) { // For PUT, only send fields that are allowed to be updated or have changed // Password might need special handling if it's not always sent // For simplicity, sending all fields here, backend should handle nulls data.id = editTenantId; // Ensure ID is part of the data for PUT res = await fetch(API_URL + '/admin/tenants/' + editTenantId, { method: 'PUT', headers: { 'Content-Type': 'application/json', 'Authorization': 'Bearer ' + token }, body: JSON.stringify(data) }); } else { res = await fetch(API_URL + '/admin/tenants', { method: 'POST', headers: { 'Content-Type': 'application/json', 'Authorization': 'Bearer ' + token }, body: JSON.stringify(data) }); } if (!res.ok) { if (res.status === 401 || res.status === 403) { logout(); return; } const result = await res.json(); throw new Error(result.error || 'فشل حفظ المتجر'); } const result = await res.json(); showNotif('تم حفظ المتجر بنجاح'); editTenantId = null; cancelEdit(); // Clear form after save switchTab('users'); } catch (e) { errorEl.textContent = e.message; errorEl.classList.add('show'); } } async function renewSubscription(id) { const tenant = tenants.find(t => t.Id === id); if (!tenant) return; const { value: months } = await Swal.fire({ title: `تجديد اشتراك ${tenant.DisplayName}`, input: 'number', inputLabel: 'عدد الأشهر للتجديد', inputValue: 1, showCancelButton: true, inputValidator: (value) => { if (!value || value <= 0) return 'الرجاء إدخال عدد صحيح موجب'; } }); if (months) { try { const res = await fetch(`${API_URL}/admin/tenants/${id}/renew`, { method: 'POST', headers: { 'Content-Type': 'application/json', 'Authorization': 'Bearer ' + token }, body: JSON.stringify({ months: parseInt(months), plan: tenant.SubscriptionPlan }) }); if (!res.ok) throw new Error((await res.json()).error || 'فشل التجديد'); showNotif('تم تجديد الاشتراك بنجاح!'); loadTenants(); } catch (e) { showNotif(e.message, true); } } } function showNotif(message, isError = false) { const notif = document.createElement('div'); notif.style.cssText = ` position: fixed; top: 20px; right: 20px; background: ${isError ? 'var(--danger)' : 'var(--accent2)'}; color: white; padding: 10px 20px; border-radius: 8px; z-index: 1000; box-shadow: 0 4px 12px rgba(0,0,0,0.15); font-size: 14px; `; notif.textContent = message; document.body.appendChild(notif); setTimeout(() => notif.remove(), 3000); }