✶ بوتيك برو
نظام إدارة البوتيكات
بوتيك برو © 2025
لوحة التحكمنظرة عامة
مبيعات اليوم
0.000
اجمالي المبيعات
0.000
التاجرات
0
مستحقات
0.000
آخر المبيعات
الفاتورةالمبلغالوقت
اكثر التاجرات مبيعا
التاجرةالمبيعاتالمستحق
؟
الموظفة النشطة
لم تُحدد بعد
نقطة البيع
السلة
السلة فارغة
الخصم
المجموع0.000
الاجمالي0.000
البوتيكات
البوتيكالموقعالعمولةتاجراتمبيعات
التاجرات
التاجرةالبوتيكالجوالمنتجاتمبيعاتهاالمستحق
البضاعة
الكودصورةالمنتجالتاجرةالسعرالكمية
المبيعات
الفاتورةالتاريخالعميلالاجماليالدفعالحالة
التسوياتمستحقات التاجرات
سجل الدفعات
التاجرةالبوتيكالتاريخالمبلغملاحظات
الموظفات
أداء الموظفات
الموظفة الفواتير إجمالي المبيعات العمولة المكتسبة الراتب إجمالي المستحق أفضل ساعة
ساعات الذروة (مبيعات البوتيك)
مقارنة الموظفات
بيانات الموظفات
الاسمالمستخدمالانضمامالراتبالعمولةالصلاحيات
التقارير تحليل أداء البوتيك
المبيعات اليومية
طرق الدفع
تقرير التاجرات التفصيلي
التاجرةقطعمبيعاتعمولة البوتيكالصافيمدفوعمتبقي
أكثر المنتجات مبيعاً
المنتجالتاجرةقطعإيراد
منتجات بطيئة الحركة
المنتجالتاجرةالكميةالسعرالقيمة
تقرير المخزون
المنتجالمتاحالقيمة
الاعدادات
🎨 ثيم الألوان
اختر لون النظام
ذهبي
وردي
أزرق
أخضر
بنفسجي
فاتح
بيانات البوتيك
العملة الاساسية
رسوم إضافية
تُطبَّق تلقائياً على كل فاتورة وتظهر في تقارير التاجرات
اكواد الهدايا
Claude AI - تحليل المنتجات من الصور
يستخدم Claude AI لقراءة صورة المنتج واستخراج: الاسم، اللون، نوع القماش، القياسات، الوصف.
احصل على مفتاح API مجاني من console.anthropic.com
>
';return;}var html='';for(var i=0;i'+c.code+''+c.label+''+(c.type==='pct'?c.val+'%':fmtM(c.val))+'
';}el.innerHTML=html;} function addCode(){var code=prompt('كود الخصم:');if(!code||!code.trim())return;var type=prompt('النوع: pct او fixed','pct');if(type!=='pct'&&type!=='fixed'){alert('نوع غير صالح');return;}var val=parseFloat(prompt(type==='pct'?'النسبة %:':'المبلغ:','10'));if(!val)return;var label=prompt('وصف:',code)||code;var maxU=parseInt(prompt('اقصى استخدامات (0 = لا محدود):','0')||'0');if(!DB.settings)DB.settings={};if(!DB.settings.codes)DB.settings.codes=[];DB.settings.codes.push({code:code.trim().toUpperCase(),type:type,val:val,label:label,uses:0,maxUses:maxU,active:true});save();renderCodes();} function delCode(i){if(!confirm('حذف؟'))return; if(DB.settings&&DB.settings.codes){DB.settings.codes.splice(i,1);save();renderCodes();}} function renderDashboard(){ fillBouts(); var today=nowDate(); var cur=DB.boutiques.find(function(b){return b.id===DB.curBout;})||DB.boutiques[0]; if(!cur)return; var bsales=DB.sales.filter(function(s){return s.boutId===cur.id&&s.status==='completed';}); var t_today=bsales.filter(function(s){return s.date===today;}).reduce(function(a,s){return a+s.total;},0); var t_all=bsales.reduce(function(a,s){return a+s.total;},0); var tc=DB.traders.filter(function(t){return t.boutId===cur.id;}).length; var due=DB.traders.filter(function(t){return t.boutId===cur.id;}).reduce(function(a,tr){var comm=cur.comm||0;var ts=DB.sales.filter(function(s){return s.status==='completed'&&s.boutId===cur.id&&s.items.some(function(it){return it.tid===tr.id;});}).reduce(function(x,s){return x+s.items.filter(function(it){return it.tid===tr.id;}).reduce(function(y,it){return y+it.qty*it.price;},0);},0);var net=ts-ts*comm/100;var paid=DB.settlements.filter(function(x){return x.traderId===tr.id;}).reduce(function(x,y){return x+y.paid;},0);return a+Math.max(0,net-paid);},0); var el; el=document.getElementById('d-today');if(el)el.textContent=fmtM(t_today); el=document.getElementById('d-total');if(el)el.textContent=fmtM(t_all); el=document.getElementById('d-tcount');if(el)el.textContent=tc; el=document.getElementById('d-due');if(el)el.textContent=fmtM(due); var ds=document.getElementById('d-sales-tbl'); if(ds){var recent=bsales.slice().reverse().slice(0,6);var rows='';for(var i=0;i'+s.inv+''+fmtM(s.total)+''+s.time+'';}ds.innerHTML=rows||'لا توجد مبيعات';} var dt=document.getElementById('d-traders-tbl'); if(dt){var tdata=DB.traders.filter(function(t){return t.boutId===cur.id;}).map(function(tr){var comm=cur.comm||0;var ts=bsales.filter(function(s){return s.items.some(function(it){return it.tid===tr.id;});}).reduce(function(a,s){return a+s.items.filter(function(it){return it.tid===tr.id;}).reduce(function(x,it){return x+it.qty*it.price;},0);},0);var net=ts-ts*comm/100;var paid=DB.settlements.filter(function(x){return x.traderId===tr.id;}).reduce(function(a,x){return a+x.paid;},0);return{tr:tr,ts:ts,rem:net-paid};}).sort(function(a,b){return b.ts-a.ts;});var rows2='';for(var j=0;j
'+x.tr.name[0]+'
'+x.tr.name+'
'+fmtM(x.ts)+''+fmtM(x.rem)+'';}dt.innerHTML=rows2||'—';} } // ═══════════════════════════════════════════ // AUTH — LOGIN / LOGOUT // ═══════════════════════════════════════════ var currentUser = null; function doLogin() { var user = (document.getElementById('login-user')||{}).value||''; var pass = (document.getElementById('login-pass')||{}).value||''; var errEl = document.getElementById('login-error'); if (!user.trim()) { if(errEl){errEl.style.display='block';errEl.textContent='ادخل اسم المستخدم';} return; } // Find staff member var staff = (DB.staff||[]).find(function(s){ return s.email === user.trim() && s.pass === pass; }); if (!staff) { if(errEl){errEl.style.display='block';errEl.textContent='اسم المستخدم أو كلمة المرور غير صحيحة';} // Shake animation var btn = document.querySelector('#login-screen .btn-gold'); if(btn){btn.style.transform='translateX(8px)';setTimeout(function(){btn.style.transform='translateX(-8px)';setTimeout(function(){btn.style.transform='';},100);},100);} return; } // Success currentUser = staff; activeStaffId = staff.id; // Hide login screen var ls = document.getElementById('login-screen'); if(ls) ls.style.display='none'; // Update sidebar user info updateUserBar(); // Apply permissions — hide nav items not in perms applyPermissions(staff.perms||[]); // Navigate to POS or dashboard var startPage = (staff.perms||[]).indexOf('نقطة البيع') > -1 ? 'pos' : 'dashboard'; var navEl = document.getElementById('nav-'+startPage); goPage(startPage, navEl); // Clear password field var passEl = document.getElementById('login-pass'); if(passEl) passEl.value=''; } function resetToDemo() { if (!confirm('سيتم حذف كل البيانات وإعادة ضبط النظام. متأكد؟')) return; localStorage.removeItem('bpro3'); location.re function showToast(msg, type, title) { var t = document.getElementById('toast'); if (!t) return; // Clear existing timer if (window._toastTimer) clearTimeout(window._toastTimer); if (window._toastBarTimer) clearInterval(window._toastBarTimer); var icons = {ok:'✔', er:'✖', warn:'⚠', info:'ℹ'}; var titles = {ok:'تم بنجاح', er:'خطأ', warn:'تنبيه', info:'معلومة'}; var tp = type || 'ok'; var iconEl = document.getElementById('toast-icon'); var titleEl = document.getElementById('toast-title'); var msgEl = document.getElementById('toast-msg'); var barEl = document.getElementById('toast-bar'); t.className = 'toast toast-' + tp; if (iconEl) iconEl.innerHTML = icons[tp] || icons.ok; if (titleEl) titleEl.textContent = title || titles[tp] || ''; if (msgEl) msgEl.textContent = msg || ''; if (barEl) { barEl.style.width = '100%'; barEl.style.transitionDuration = '3s'; setTimeout(function(){ barEl.style.width = '0%'; }, 50); } t.classList.add('show'); window._toastTimer = setTimeout(function(){ t.classList.remove('show'); }, 3200); } function showConfirm(msg, onOk, onCancel) { var existing = document.getElementById('confirm-dialog'); if (existing) existing.remove(); window._confirmOk = onOk; window._confirmCancel = onCancel; var el = document.createElement('div'); el.id = 'confirm-dialog'; el.style.cssText = 'position:fixed;inset:0;background:rgba(0,0,0,.7);z-index:99998;display:flex;align-items:center;justify-content:center;padding:16px;backdrop-filter:blur(4px)'; var box = document.createElement('div'); box.style.cssText = 'background:var(--s1);border:1px solid var(--br);border-radius:16px;padding:28px;width:320px;text-align:center;box-shadow:0 16px 48px rgba(0,0,0,.5)'; var icon = document.createElement('div'); icon.style.cssText = 'font-size:36px;margin-bottom:12px'; icon.innerHTML = '⚠️'; var txt = document.createElement('div'); txt.style.cssText = 'font-size:15px;font-weight:700;margin-bottom:8px;line-height:1.5'; txt.textContent = msg; var btns = document.createElement('div'); btns.style.cssText = 'display:flex;gap:10px;margin-top:20px'; var cancelBtn = document.createElement('button'); cancelBtn.textContent = 'إلغاء'; cancelBtn.style.cssText = 'flex:1;padding:11px;background:var(--s2);border:1px solid var(--br);border-radius:9px;color:var(--tx);cursor:pointer;font-family:Tajawal;font-size:14px'; cancelBtn.onclick = function(){ document.getElementById('confirm-dialog').remove(); if(window._confirmCancel) window._confirmCancel(); }; var okBtn = document.createElement('button'); okBtn.textContent = 'تأكيد'; okBtn.style.cssText = 'flex:1;padding:11px;background:linear-gradient(135deg,var(--er),#c03030);border:none;border-radius:9px;color:#fff;cursor:pointer;font-family:Tajawal;font-size:14px;font-weight:700'; okBtn.onclick = function(){ document.getElementById('confirm-dialog').remove(); if(window._confirmOk) window._confirmOk(); }; btns.appendChild(cancelBtn); btns.appendChild(okBtn); box.appendChild(icon); box.appendChild(txt); box.appendChild(btns); el.appendChild(box); document.body.appendChild(el); } function saveCostSetting(){ if(!DB.settings) DB.settings={}; var el=document.getElementById('cfg-hide-cost'); DB.settings.hideCost = el ? el.checked : false; save(); applyCostVisibility(); showToast(DB.settings.hideCost?'تم إخفاء سعر التكلفة':'ظهر سعر التكلفة مجدداً','ok'); } function applyCostVisibility(){ var hide=(DB.settings&&DB.settings.hideCost); var costRows=document.querySelectorAll('.cost-field'); for(var i=0;i -1) ? '' : 'none'; }); } // Allow Enter key on login form document.addEventListener('keydown', function(e){ var ls = document.getElementById('login-screen'); if(ls && ls.style.display !== 'none' && e.key === 'Enter') doLogin(); }); // Active staff tracking var activeStaffId = null; function selectStaff(id) { activeStaffId = id; var nameEl = document.getElementById('pos-staff-name'); var avatarEl = document.getElementById('pos-staff-avatar'); if (id) { var s = (DB.staff||[]).find(function(x){return x.id===id;}); if (s) { if (nameEl) nameEl.textContent = s.name; if (avatarEl) { avatarEl.textContent = s.name[0]; avatarEl.style.background = 'linear-gradient(135deg,var(--gold2),var(--rose))'; } } } else { if (nameEl) nameEl.textContent = 'لم تُحدد بعد'; if (avatarEl) { avatarEl.textContent = '؟'; avatarEl.style.background = 'var(--s3)'; } } closeOv('ov-select-staff'); } function openStaffSelector() { var list = document.getElementById('staff-select-list'); if (!list) return; var staff = DB.staff||[]; if (!staff.length) { list.innerHTML = '
لا توجد موظفات
'; openOv('ov-select-staff'); return; } var html = ''; for (var i=0; i'; html += '
' + s.name[0] + '
'; html += '
'; html += '
' + s.name + '
'; html += '
' + s.email + '
'; html += '
'; if (isActive) html += ''; html += ''; } list.innerHTML = html; openOv('ov-select-staff'); } function getVAT(){ return parseFloat((DB.settings&&DB.settings.vat)||0)||0; } function getCardFee(){ return parseFloat((DB.settings&&DB.settings.cardFee)||0)||0; } // TRADER REPORT var _traderReportId = null; function setTrRepPeriod(p){ var t=nowDate(),f='',d=new Date(); if(p==='month'){f=t.slice(0,8)+'01';} else if(p==='last'){ d.setDate(0); var y=d.getFullYear(),m=String(d.getMonth()+1).padStart(2,'0'); f=y+'-'+m+'-01'; t=y+'-'+m+'-'+String(d.getDate()).padStart(2,'0'); } var fe=document.getElementById('tr-rep-from'); var te=document.getElementById('tr-rep-to'); if(fe)fe.value=f; if(te)te.value=t; buildTraderReport(); } function openTraderReport(tid){ _traderReportId=tid; var t=nowDate(),f=t.slice(0,8)+'01'; var fe=document.getElementById('tr-rep-from'); var te=document.getElementById('tr-rep-to'); if(fe)fe.value=f; if(te)te.value=t; buildTraderReport(); openOv('ov-trader-report'); } function buildTraderReport(){ var tid=_traderReportId; if(!tid)return; var tr=DB.traders.find(function(x){return x.id===tid;}); if(!tr)return; var b=DB.boutiques.find(function(x){return x.id===tr.boutId;})||{}; var comm=b.comm||0, vat=getVAT(), cFee=getCardFee(); var from=(document.getElementById('tr-rep-from')||{}).value||''; var to=(document.getElementById('tr-rep-to')||{}).value||''; var title=document.getElementById('tr-rep-title'); if(title)title.textContent='تقرير: '+tr.name; var sales=DB.sales.filter(function(s){ if(s.status!=='completed')return false; if(from&&s.dateto)return false; return s.items.some(function(it){return it.tid===tid;}); }); var totalItems=0,totalRevenue=0,cardSales=0,saleRows=''; sales.forEach(function(s){ var trItems=s.items.filter(function(it){return it.tid===tid;}); var trRev=trItems.reduce(function(a,it){return a+it.qty*it.price;},0); var trQty=trItems.reduce(function(a,it){return a+it.qty;},0); var trCardFee=(s.method==='card'&&cFee)?trRev*cFee/100:0; totalItems+=trQty; totalRevenue+=trRev; if(s.method==='card')cardSales+=trRev; var mL={cash:'نقدا',card:'بطاقة',transfer:'تحويل'}[s.method]||s.method; saleRows+='' +''+s.date+''+s.inv+'' +''+trItems.map(function(it){return it.name+' x'+it.qty;}).join(', ')+'' +''+fmtM(trRev)+'' +''+mL+'' +(trCardFee>0?'-'+fmtM(trCardFee)+'':'—') +''; }); var boutCommAmt=totalRevenue*comm/100; var vatAmt=vat?totalRevenue*vat/100:0; var cardFeeAmt=cFee?cardSales*cFee/100:0; var netDue=totalRevenue-boutCommAmt-vatAmt-cardFeeAmt; var settles=DB.settlements.filter(function(x){return x.traderId===tid&&(!from||x.date>=from)&&(!to||x.date<=to);}); var totalPaid=settles.reduce(function(a,x){return a+x.paid;},0); var remaining=netDue-totalPaid; var html=''; html+='
'; html+='
الفترة: '+(from||'من البداية')+' — '+(to||'حتى الآن')+'
'; html+='
'; html+='
اجمالي مبيعاتك
'+fmtM(totalRevenue)+'
'; html+='
عدد القطع
'+totalItems+'
'; html+='
'; html+='
'; html+='
تفاصيل الخصومات
'; html+='
اجمالي مبيعاتك'+fmtM(totalRevenue)+'
'; html+='
ايجار البوتيك ('+comm+'%)- '+fmtM(boutCommAmt)+'
'; if(vatAmt>0)html+='
ضريبة VAT ('+vat+'%)- '+fmtM(vatAmt)+'
'; if(cardFeeAmt>0)html+='
رسوم جهاز الدفع ('+cFee+'%)- '+fmtM(cardFeeAmt)+'
'; html+='
الصافي المستحق لك'+fmtM(netDue)+'
'; html+='
'; html+='
'; html+='
الدفعات المستلمة
'; if(settles.length){settles.forEach(function(x){html+='
'+x.date+(x.notes?' - '+x.notes:'')+''+fmtM(x.paid)+'
';});} else{html+='
لا توجد دفعات
';} html+='
المتبقي'+fmtM(remaining)+'
'; html+='
'; if(sales.length){ html+='
تفاصيل الفواتير ('+sales.length+')
'; html+='
'+saleRows+'
التاريخالفاتورةالبضاعةالمبلغالدفعرسوم الجهاز
'; } var body=document.getElementById('tr-rep-body'); if(body)body.innerHTML=html; window._lastTraderReport={trader:tr,boutique:b,from:from,to:to,totalRevenue:totalRevenue,totalItems:totalItems,boutCommAmt:boutCommAmt,vatAmt:vatAmt,cardFeeAmt:cardFeeAmt,netDue:netDue,totalPaid:totalPaid,remaining:remaining,comm:comm,vat:vat,cFee:cFee,cardSales:cardSales}; } function sendTraderReportWA(){ var r=window._lastTraderReport; if(!r||!r.trader.phone){alert('لا يوجد رقم جوال');return;} var ph=r.trader.phone.replace(/\D/g,''); if(ph.indexOf('968')!==0)ph='968'+ph.replace(/^0/,''); var lines=[ 'كشف حساب - '+(r.boutique.name||'البوتيك'), 'التاجرة: '+r.trader.name, 'الفترة: '+(r.from||'من البداية')+' الى '+(r.to||'الآن'), '---', 'اجمالي مبيعاتك: '+fmtM(r.totalRevenue), 'عدد القطع: '+r.totalItems, '---', 'ايجار البوتيك '+r.comm+'%: -'+fmtM(r.boutCommAmt) ]; if(r.vatAmt>0)lines.push('ضريبة VAT '+r.vat+'%: -'+fmtM(r.vatAmt)); if(r.cardFeeAmt>0)lines.push('رسوم جهاز الدفع '+r.cFee+'%: -'+fmtM(r.cardFeeAmt)); lines.push('---'); lines.push('الصافي المستحق لك: '+fmtM(r.netDue)); if(r.totalPaid>0)lines.push('تم استلامه: '+fmtM(r.totalPaid)); lines.push('المتبقي: '+fmtM(r.remaining)); lines.push('---'); lines.push('شكرا لتعاملك معنا'); window.open('https://wa.me/'+ph+'?text='+encodeURIComponent(lines.join('\n')),'_blank'); } // ═══════════════════════════════════════════ // SIZE FIELDS // ═══════════════════════════════════════════ var SIZE_TEMPLATES = { abaya: [{id:'length',label:'الطول (سم)'},{id:'chest',label:'الصدر (سم)'},{id:'shoulder',label:'الكتف (سم)'},{id:'sleeve',label:'الكم (سم)'},{id:'waist',label:'الخصر (سم)'},{id:'size_label',label:'المقاس (S/M/L/XL)'}], top: [{id:'chest',label:'الصدر (سم)'},{id:'shoulder',label:'الكتف (سم)'},{id:'length',label:'الطول (سم)'},{id:'sleeve',label:'الكم (سم)'},{id:'size_label',label:'المقاس'}], pants: [{id:'waist',label:'الخصر (سم)'},{id:'hips',label:'الورك (سم)'},{id:'length',label:'الطول (سم)'},{id:'size_label',label:'المقاس'}], scarf: [{id:'length',label:'الطول (سم)'},{id:'width',label:'العرض (سم)'},{id:'material',label:'الخامة'}], bag: [{id:'width',label:'العرض (سم)'},{id:'height',label:'الارتفاع (سم)'},{id:'depth',label:'العمق (سم)'},{id:'color',label:'اللون'}], shoes: [{id:'size_label',label:'المقاس'},{id:'color',label:'اللون'},{id:'material',label:'الخامة'}], accessory: [{id:'size_label',label:'المقاس/الحجم'},{id:'color',label:'اللون'},{id:'material',label:'الخامة'}], custom:[{id:'f1',label:'قياس 1'},{id:'f2',label:'قياس 2'},{id:'f3',label:'قياس 3'},{id:'f4',label:'قياس 4'},{id:'f5',label:'قياس 5'},{id:'f6',label:'قياس 6'}] }; var _aiResult = null; function buildSizeFields() { var type = (document.getElementById('size-type')||{}).value; var container = document.getElementById('size-fields'); if (!container) return; if (!type) { container.innerHTML = ''; return; } var fields = SIZE_TEMPLATES[type] || []; // Load existing values if editing var existing = {}; try { existing = JSON.parse((document.getElementById('p-sizes')||{}).value||'{}'); } catch(e) {} var html = ''; for (var i=0; i'; html += ''; html += ''; } container.innerHTML = html; } function collectSizes() { var type = (document.getElementById('size-type')||{}).value; if (!type) return ''; var fields = SIZE_TEMPLATES[type] || []; var obj = { _type: type }; for (var i=0; i -1) continue; parts.push(obj[k]); } return parts.slice(0,3).join(' / '); } catch(e) { return ''; } } // ═══════════════════════════════════════════ // AI PRODUCT SCAN // ═══════════════════════════════════════════ function getApiKey() { return DB.settings && DB.settings.apiKey ? DB.settings.apiKey : ''; } function saveApiKey() { var key = (document.getElementById('cfg-apikey')||{}).value||''; if (!key.trim()) { alert('ادخل المفتاح'); return; } if (!DB.settings) DB.settings = {}; DB.settings.apiKey = key.trim(); save(); alert('تم حفظ المفتاح'); } function testApiKey() { var el = document.getElementById('api-test-result'); if (el) { el.style.color='var(--mu)'; el.textContent='جاري الاختبار...'; } var key = getApiKey(); if (!key) { if(el){el.style.color='var(--er)';el.textContent='لا يوجد مفتاح - احفظه اولا';} return; } fetch('https://api.anthropic.com/v1/messages', { method:'POST', headers:{'Content-Type':'application/json','x-api-key':key,'anthropic-version':'2023-06-01'}, body:JSON.stringify({model:'claude-haiku-4-5-20251001',max_tokens:20,messages:[{role:'user',content:'قل نعم فقط'}]}) }).then(function(r){return r.json();}).then(function(d){ if(d.content&&d.content[0]){if(el){el.style.color='var(--ok)';el.textContent='المفتاح يعمل';}} else{if(el){el.style.color='var(--er)';el.textContent='خطأ: '+(d.error&&d.error.message||'غير معروف');}} }).catch(function(e){if(el){el.style.color='var(--er)';el.textContent='فشل الاتصال';}}); } function aiScanProduct(input) { if (!input.files || !input.files[0]) return; var key = getApiKey(); if (!key) { alert('اضف مفتاح Claude API في الاعدادات اولا'); return; } var statusEl = document.getElementById('ai-status'); var wrapEl = document.getElementById('ai-wrap'); var prevEl = document.getElementById('ai-prev'); var outEl = document.getElementById('ai-out'); var applyBtn = document.getElementById('ai-apply'); var btn = document.getElementById('ai-btn'); if(statusEl) { statusEl.style.color='var(--gold)'; statusEl.textContent='جاري قراءة الصورة...'; } if(btn) btn.disabled = true; var reader = new FileReader(); reader.onload = function(e) { var b64 = e.target.result.split(',')[1]; var mime = input.files[0].type || 'image/jpeg'; if(prevEl) { prevEl.src=e.target.result; } if(wrapEl) { wrapEl.style.display='block'; } if(outEl) { outEl.textContent='جاري التحليل...'; } // Get category from size-type if selected var sizeType = (document.getElementById('size-type')||{}).value || ''; var catHint = sizeType ? ' (نوع المنتج: ' + sizeType + ')' : ''; var prompt = 'انت خبير في الموضة والملابس. حلل هذه الصورة لمنتج في بوتيك'+catHint+'.' +' استخرج المعلومات التالية وأجب بهذا التنسيق فقط: ' +'الاسم: [اسم المنتج] | ' +'اللون: [الالوان] | ' +'الخامة: [نوع القماش] | ' +'المقاس: [المقاس ان كان واضحا] | ' +'الطول: [بالسم ان كان واضحا] | ' +'الصدر: [بالسم ان كان واضحا] | ' +'الوصف: [وصف مختصر] | ' +'السعر المقترح: [بالريال العماني] ' +'اذا لم تكن المعلومة واضحة اكتب: غير محدد'; fetch('https://api.anthropic.com/v1/messages', { method: 'POST', headers: { 'Content-Type':'application/json', 'x-api-key':key, 'anthropic-version':'2023-06-01' }, body: JSON.stringify({ model: 'claude-haiku-4-5-20251001', max_tokens: 400, messages: [{ role: 'user', content: [ { type:'image', source:{ type:'base64', media_type:mime, data:b64 } }, { type:'text', text:prompt } ] }] }) }) .then(function(r) { return r.json(); }) .then(function(d) { if(btn) btn.disabled = false; if (d.content && d.content[0] && d.content[0].text) { var text = d.content[0].text; _aiResult = parseAiResult(text); if(outEl) outEl.innerHTML = text.replace(/\n/g,'
').replace(/\|/g,'
'); if(applyBtn) applyBtn.style.display = 'inline-flex'; if(statusEl) { statusEl.style.color='var(--ok)'; statusEl.textContent='تم التحليل'; } } else { var errMsg = d.error ? d.error.message : 'غير معروف'; if(outEl) { outEl.style.color='var(--er)'; outEl.textContent='خطأ: '+errMsg; } if(statusEl) { statusEl.style.color='var(--er)'; statusEl.textContent='فشل'; } } }) .catch(function(e) { if(btn) btn.disabled = false; if(outEl) { outEl.style.color='var(--er)'; outEl.textContent='فشل الاتصال بـ Claude'; } if(statusEl) { statusEl.style.color='var(--er)'; statusEl.textContent='خطأ في الاتصال'; } }); }; reader.readAsDataURL(input.files[0]); } function parseAiResult(text) { var result = {}; var parts = text.indexOf('|')>-1 ? text.split('|') : text.split('\n'); for (var i=0; ito) return false; return true; }); // KPI cards var totalSal=list.reduce(function(a,s){return a+(s.salary||0);},0); var totalComm=list.reduce(function(a,s){ var ss=allSales.filter(function(x){return x.staffId===s.id;}); return a+calcStaffComm(s,ss); },0); var sc=document.getElementById('staff-stats-cards'); if(sc){ sc.innerHTML= '
عدد الموظفات
'+list.length+'
' +'
إجمالي الرواتب
'+fmtM(totalSal)+'
' +'
إجمالي العمولات
'+fmtM(totalComm)+'
' +'
إجمالي المستحقات
'+fmtM(totalSal+totalComm)+'
'; } // Performance table var perf=document.getElementById('tbl-staff-perf'); if(perf){ var rows=''; for(var i=0;ibestC){bestC=hmap[h];bestH=h+':00';}}); rows+='' +'
'+st.name[0]+'
'+st.name+'
' +''+ss.length+'' +''+fmtM(sTotal)+'' +''+fmtM(sComm)+'' +''+fmtM(st.salary||0)+'' +''+fmtM(sDue)+'' +''+bestH+'' +'' +''; } perf.innerHTML=rows||'لا توجد موظفات'; } // Peak hours chart var peakEl=document.getElementById('peak-chart'); var peakLbl=document.getElementById('peak-labels'); if(peakEl){ var hours={}; for(var h=8;h<=22;h++) hours[String(h).padStart(2,'0')]=0; allSales.forEach(function(x){ if(!x.time) return; var hk=x.time.slice(0,2); if(hours[hk]!==undefined) hours[hk]+=x.total; }); var maxH=Math.max.apply(null,Object.keys(hours).map(function(k){return hours[k];}))||1; var ch='',lb=''; Object.keys(hours).forEach(function(hk){ var val=hours[hk]; var ht=Math.max(2,Math.round(val/maxH*90)); ch+='
' +(val>0?'
'+Math.round(val)+'
':'') +'
' +'
'; lb+='
'+parseInt(hk)+'
'; }); peakEl.innerHTML=ch; if(peakLbl)peakLbl.innerHTML=lb; } // Staff comparison bars var cmp=document.getElementById('staff-compare'); if(cmp){ var data=[]; for(var j=0;j0;}).sort(function(a,b){return b.total-a.total;}); var maxT=data.length?data[0].total:1; var html=''; if(!data.length){ html='
ربط المبيعات بالموظفة يتم تلقائياً عند تسجيل الدخول قبل إتمام البيع
'; } else { data.forEach(function(x){ var pct=Math.round(x.total/maxT*100); html+='
' +'
' +''+x.name+''+fmtM(x.total)+' ('+x.count+' فاتورة)
' +'
' +'
' +'
'; }); } cmp.innerHTML=html; } } function saveBoutiqueSettings(){ var b = DB.boutiques && DB.boutiques[0]; if (!b) { b = {id:'b1', name:'', loc:'', phone:'', comm:20, notes:''}; if (!DB.boutiques) DB.boutiques = []; DB.boutiques[0] = b; } var bn = document.getElementById('cfg-bname'); var bl = document.getElementById('cfg-bloc'); var bp = document.getElementById('cfg-bphone'); var bc = document.getElementById('cfg-bcomm'); if(bn) b.name = bn.value.trim(); if(bl) b.loc = bl.value.trim(); if(bp) b.phone = bp.value.trim(); if(bc) b.comm = parseFloat(bc.value)||0; DB.curBout = b.id; save(); fillBouts(); alert('تم حفظ بيانات البوتيك'); } // ═══════════════════════════════════════════ // THEME SYSTEM // ═══════════════════════════════════════════ function applyTheme(theme) { var body = document.body; var themes = ['theme-rose','theme-ocean','theme-forest','theme-purple','theme-light']; themes.forEach(function(t){ body.classList.remove(t); }); if (theme) body.classList.add(theme); if (!DB.settings) DB.settings = {}; DB.settings.theme = theme; save(); // Update active border on theme buttons var btns = document.querySelectorAll('.theme-btn'); for (var i=0;i 0 && p.qty <= threshold; }); if (!low.length) return; var existing = document.getElementById('stock-alert-banner'); if (existing) existing.remove(); var banner = document.createElement('div'); banner.id = 'stock-alert-banner'; banner.style.cssText = 'position:fixed;top:14px;left:50%;transform:translateX(-50%);background:rgba(224,92,92,.95);border-radius:10px;padding:12px 18px;z-index:8000;display:flex;align-items:center;gap:10px;font-size:13px;color:#fff;box-shadow:0 4px 20px rgba(0,0,0,.3);max-width:400px'; banner.innerHTML = '⚠️' + '
تنبيه مخزون منخفض
' + '
' + low.length + ' منتج وصل للحد الأدنى (' + threshold + ' قطع)
' + '' + ''; document.body.appendChild(banner); setTimeout(function(){ if(banner.parentElement) banner.remove(); }, 8000); } function showLowStock() { var threshold = parseInt((DB.settings||{}).stockAlert || 5); var low = DB.products.filter(function(p){ return p.qty > 0 && p.qty <= threshold; }); var msg = 'منتجات توشك النفاد:\n'; low.forEach(function(p){ var t = DB.traders.find(function(x){return x.id===p.traderId;})||{}; msg += '• ' + p.name + ' (' + (t.name||'') + ') — متبقي: ' + p.qty + '\n'; }); alert(msg); } function saveStockSettings() { if (!DB.settings) DB.settings = {}; var el = document.getElementById('cfg-stock-alert'); var chk = document.getElementById('cfg-stock-notify'); DB.settings.stockAlert = el ? parseInt(el.value)||5 : 5; DB.settings.stockNotify = chk ? chk.checked : true; save(); showToast('تم حفظ إعدادات التنبيه', 'ok'); checkStockAlerts(); } function saveTaxSettings() { if (!DB.settings) DB.settings = {}; var who = document.querySelector('input[name="tax-who"]:checked'); var pct = document.getElementById('cfg-tax-pct'); DB.settings.taxWho = who ? who.value : 'boutique'; DB.settings.vat = pct ? parseFloat(pct.value)||0 : 0; save(); showToast('تم حفظ إعدادات الضريبة', 'ok'); } // ═══════════════════════════════════════════ // TRADER COLOR + LOGO // ═══════════════════════════════════════════ function setTraderColor(color) { var inp = document.getElementById('t-color'); var prev = document.getElementById('t-color-preview'); if (inp) inp.value = color; if (prev) prev.style.background = color; } function prevTraderLogo(inp) { if (!inp.files || !inp.files[0]) return; var reader = new FileReader(); reader.onload = function(e) { var prev = document.getElementById('t-logo-prev'); var hid = document.getElementById('t-logo'); if (prev) prev.innerHTML = ''; if (hid) hid.value = e.target.result; }; reader.readAsDataURL(inp.files[0]); } function clearTraderLogo() { var prev = document.getElementById('t-logo-prev'); var hid = document.getElementById('t-logo'); var fi = document.getElementById('t-logo-file'); if (prev) prev.innerHTML = '💼'; if (hid) hid.value = ''; if (fi) fi.value = ''; } // ═══════════════════════════════════════════ // INIT // ═══════════════════════════════════════════ // ═══════════════════════════════════════════ // PREMIUM TOAST SYSTEM // ═══════════════════════════════════════════ var _toastId = 0; function showToast(msg, type, title) { var wrap = document.getElementById('toast-wrap'); if (!wrap) { alert(msg); return; } var tp = type || 'ok'; var icons = {ok:'✔', er:'✖', warn:'⚠', info:'ℹ'}; var titles = {ok:'تم بنجاح', er:'خطأ', warn:'تنبيه', info:'معلومة'}; var id = 'toast-' + (++_toastId); var el = document.createElement('div'); el.id = id; el.className = 'toast toast-' + tp; el.innerHTML = '
' + '
' + (icons[tp]||icons.ok) + '
' + '
' + '
' + (title || titles[tp] || '') + '
' + '
' + msg + '
' + '
' + '' + '
' + '
'; wrap.appendChild(el); setTimeout(function(){ el.classList.add('show'); }, 10); setTimeout(function(){ var bar = document.getElementById(id + '-bar'); if (bar) bar.style.width = '0%'; }, 50); setTimeout(function(){ el.classList.remove('show'); setTimeout(function(){ if(el.parentElement) el.remove(); }, 300); }, 3500); } // ═══════════════════════════════════════════ // COST FIELD VISIBILITY // ═══════════════════════════════════════════ function toggleCostField() { var chk = document.getElementById('cfg-hide-cost'); if (!DB.settings) DB.settings = {}; DB.settings.hideCost = chk ? chk.checked : false; save(); applyCostVisibility(); showToast(DB.settings.hideCost ? 'تم إخفاء سعر التكلفة' : 'تم إظهار سعر التكلفة', 'ok'); } function applyCostVisibility() { var hide = DB.settings && DB.settings.hideCost; var wrap = document.getElementById('cost-field-wrap'); if (wrap) wrap.style.display = hide ? 'none' : ''; } load(); // Ensure admin account always exists if (!DB.staff) DB.staff = []; var _hasAdmin = DB.staff.find(function(x){ return x.email === 'admin'; }); if (!_hasAdmin) { DB.staff.push({ id:'st1', name:'مدير النظام', email:'admin', pass:'admin123', salary:0, join:'2024-01-01', end:'', ct:'none', cp:0, cf:0, perms:['لوحة التحكم','نقطة البيع','البوتيكات','التاجرات','البضاعة', 'المبيعات','التسويات','الموظفات','التقارير','الاعدادات'], active:true }); save(); } // Ensure settings exist if (!DB.settings) { DB.settings = { currency:'OMR', sym:'ر.ع', rates:{USD:2.59,AED:0.706,SAR:0.691,EUR:2.80,GBP:3.26,KWD:0.122}, codes:[], vat:0, cardFee:0 }; save(); } fillBouts(); loadTheme(); checkStockAlerts(); applyCostVisibility(); applyCostVisibility(); var _sdEl = document.getElementById('sales-date'); if (_sdEl) _sdEl.value = nowDate(); // Focus login username var _uEl = document.getElementById('login-user'); if (_uEl) setTimeout(function(){ _uEl.focus(); }, 100); function save(){try{localStorage.setItem('bpro3',JSON.stringify(DB));}catch(e){}} function load(){try{var d=localStorage.getItem('bpro3');if(d){DB=JSON.parse(d);return;}}catch(e){}seedDemo();} function seedDemo(){ DB.boutiques=[{id:'b1',name:'بوتيك لالة',loc:'مسقط - الموج',phone:'',comm:20,notes:''},{id:'b2',name:'بوتيك نجمة',loc:'مسقط - المطرح',phone:'',comm:15,notes:''}]; DB.curBout='b1'; DB.traders=[{id:'t1',name:'ام خالد',phone:'+96891234567',idn:'',boutId:'b1',notes:''},{id:'t2',name:'ام سالم',phone:'+96892345678',idn:'',boutId:'b1',notes:''},{id:'t3',name:'ام ماجد',phone:'+96893456789',idn:'',boutId:'b2',notes:''}]; var t=new Date().toISOString().slice(0,10); DB.products=[{id:'p1',sku:'SKU001',name:'عباية مطرزة',traderId:'t1',boutId:'b1',cost:25,price:45,qty:3,cat:'عبايات',img:'',notes:''},{id:'p2',sku:'SKU002',name:'طرحة حرير',traderId:'t1',boutId:'b1',cost:8,price:18,qty:5,cat:'طرح',img:'',notes:''},{id:'p3',sku:'SKU003',name:'حقيبة جلد',traderId:'t2',boutId:'b1',cost:12,price:28,qty:2,cat:'حقائب',img:'',notes:''},{id:'p4',sku:'SKU004',name:'اكسسوار فضي',traderId:'t2',boutId:'b1',cost:5,price:12,qty:8,cat:'اكسسوارات',img:'',notes:''},{id:'p5',sku:'SKU005',name:'عطر عود',traderId:'t3',boutId:'b2',cost:30,price:65,qty:4,cat:'عطور',img:'',notes:''}]; DB.sales=[{id:'s1',boutId:'b1',inv:'INV-1001',date:t,time:'09:00',method:'cash',items:[{pid:'p1',name:'عباية مطرزة',qty:1,price:45,tid:'t1'}],sub:45,disc:0,total:45,cname:'',cphone:'',status:'completed'},{id:'s2',boutId:'b1',inv:'INV-1002',date:t,time:'11:30',method:'card',items:[{pid:'p4',name:'اكسسوار فضي',qty:2,price:12,tid:'t2'}],sub:24,disc:0,total:24,cname:'',cphone:'',status:'completed'}]; DB.settlements=[]; DB.staff=[{id:'st1',name:'مدير النظام',email:'admin',pass:'admin123',salary:0,join:'2024-01-01',end:'',ct:'none',cp:0,cf:0,perms:PERMS.slice(),active:true}]; DB.inv=1003; DB.settings={currency:'OMR',sym:'ر.ع',rates:{USD:2.59,AED:0.706,SAR:0.691,EUR:2.80,GBP:3.26,KWD:0.122},codes:[]}; save(); } function sym(){return DB.settings&&DB.settings.sym?DB.settings.sym:'ر.ع';} function fmt(n){return(parseFloat(n)||0).toFixed(3);} function fmtM(n){return fmt(n)+' '+sym();} function nowDate(){return new Date().toISOString().slice(0,10);} function nowTime(){return new Date().toLocaleTimeString('ar',{hour:'2-digit',minute:'2-digit'});} function nextInv(){return 'INV-'+(DB.inv++);} function goPage(id,navId){ var pgs=document.querySelectorAll('.pg'); for(var i=0;i'+b.name+'';}).join(''); var ids=['t-bout','p-bout','dash-bout','pos-b']; for(var i=0;i'+t.name+(b?' ('+b.name+')':'')+'';}).join(''); } function switchBout(id){DB.curBout=id;save();renderDashboard();} function renderBoutiques(){ var tb=document.getElementById('tbl-bouts');if(!tb)return; var rows=''; for(var i=0;i'+(b.loc||'—')+''+b.comm+'%'+tc+''+fmtM(ms)+' ';} tb.innerHTML=rows||'لا توجد بوتيكات'; } function openBoutForm(id){var b=id?DB.boutiques.find(function(x){return x.id===id;}):null;document.getElementById('b-title').textContent=b?'تعديل البوتيك':'بوتيك جديد';document.getElementById('b-id').value=b?b.id:'';document.getElementById('b-name').value=b?b.name:'';document.getElementById('b-loc').value=b?(b.loc||''):'';document.getElementById('b-phone').value=b?(b.phone||''):'';document.getElementById('b-comm').value=b?b.comm:'20';document.getElementById('b-notes').value=b?(b.notes||''):'';openOv('ov-boutique');} function editBout(id){openBoutForm(id);} function saveBout(){var id=document.getElementById('b-id').value;var name=document.getElementById('b-name').value.trim();if(!name){showToast('ادخل الاسم','er','حقل مطلوب');return;}var obj={id:id||'b'+Date.now(),name:name,loc:document.getElementById('b-loc').value.trim(),phone:document.getElementById('b-phone').value.trim(),comm:parseFloat(document.getElementById('b-comm').value)||0,notes:document.getElementById('b-notes').value.trim()};if(id){var i=DB.boutiques.findIndex(function(x){return x.id===id;});if(i>-1)DB.boutiques[i]=obj;}else{DB.boutiques.push(obj);if(!DB.curBout)DB.curBout=obj.id;}save();closeOv('ov-boutique');fillBouts();renderBoutiques();showToast('تم حفظ البوتيك','ok');} function delBout(id){if(!confirm('حذف؟'))return; DB.boutiques=DB.boutiques.filter(function(b){return b.id!==id;});if(DB.curBout===id)DB.curBout=DB.boutiques[0]?DB.boutiques[0].id:null;save();fillBouts();renderBoutiques();} function renderTraders(){ var tb=document.getElementById('tbl-traders');if(!tb)return; var q=((document.getElementById('trader-q')||{}).value||'').toLowerCase(); var tlist=q?DB.traders.filter(function(t){return t.name.toLowerCase().indexOf(q)>-1||(t.phone&&t.phone.indexOf(q)>-1);}):DB.traders; var rows=''; for(var i=0;i
'+tr.name[0]+'
'+tr.name+'
'+(b.name||'—')+''+(tr.phone||'—')+''+prods+''+fmtM(tsales)+''+fmtM(trem)+' ';} tb.innerHTML=rows||'لا توجد تاجرات'; } function openTraderForm(id){var t=id?DB.traders.find(function(x){return x.id===id;}):null;document.getElementById('t-title').textContent=t?'تعديل التاجرة':'اضافة تاجرة';document.getElementById('t-id').value=t?t.id:'';document.getElementById('t-name').value=t?t.name:'';document.getElementById('t-phone').value=t?(t.phone||''):'';document.getElementById('t-idn').value=t?(t.idn||''):'';document.getElementById('t-notes').value=t?(t.notes||''):'';fillBouts();var tb=document.getElementById('t-bout');if(tb&&t)tb.value=t.boutId;openOv('ov-trader');} function editTrader(id){openTraderForm(id);} function saveTrader(){var id=document.getElementById('t-id').value;var name=document.getElementById('t-name').value.trim();if(!name){showToast('ادخل الاسم','er','حقل مطلوب');return;}var obj={id:id||'t'+Date.now(),name:name,phone:document.getElementById('t-phone').value.trim(),idn:document.getElementById('t-idn').value.trim(),boutId:document.getElementById('t-bout').value,notes:document.getElementById('t-notes').value.trim()};if(id){var i=DB.traders.findIndex(function(x){return x.id===id;});if(i>-1)DB.traders[i]=obj;}else DB.traders.push(obj);save();closeOv('ov-trader');renderTraders();showToast('تم حفظ التاجرة','ok');} function delTrader(id){if(!confirm('حذف؟'))return; DB.traders=DB.traders.filter(function(t){return t.id!==id;});save();renderTraders();} function renderProducts(){ var tb=document.getElementById('tbl-prods');if(!tb)return; var q=(document.getElementById('prod-q')||{}).value||''; var list=q?DB.products.filter(function(p){return p.name.indexOf(q)>-1||p.sku.indexOf(q)>-1;}):DB.products.slice(); var rows=''; for(var i=0;i'+p.sku+''+(p.img?'':'📦')+''+p.name+'
'+(p.cat||'')+'
'+(t?t.name:'—')+''+fmtM(p.price)+''+p.qty+' ';} tb.innerHTML=rows||'لا توجد منتجات'; } function openProdForm(id){var p=id?DB.products.find(function(x){return x.id===id;}):null;document.getElementById('p-title').textContent=p?'تعديل المنتج':'اضافة منتج';document.getElementById('p-id').value=p?p.id:'';document.getElementById('p-sku').value=p?p.sku:('SKU'+String(DB.products.length+1).padStart(3,'0'));document.getElementById('p-name').value=p?p.name:'';document.getElementById('p-cost').value=p?p.cost:'';document.getElementById('p-price').value=p?p.price:'';document.getElementById('p-qty').value=p?p.qty:'1';document.getElementById('p-cat').value=p?(p.cat||''):'';document.getElementById('p-notes').value=p?(p.notes||''):'';document.getElementById('p-img').value=p?(p.img||''):'';var prev=document.getElementById('p-img-prev');if(prev)prev.innerHTML=(p&&p.img)?'':'📦';fillTraders('p-trader');fillBouts();var pt=document.getElementById('p-trader');var pb=document.getElementById('p-bout');if(p&&pt)pt.value=p.traderId;if(p&&pb)pb.value=p.boutId;var aiWrap=document.getElementById('ai-wrap');if(aiWrap)aiWrap.style.display='none';var aiSt=document.getElementById('ai-status');if(aiSt)aiSt.textContent='';_aiResult=null;var pSizes=document.getElementById('p-sizes');if(pSizes)pSizes.value=p?(p.sizes||''):'';loadSizesIntoForm(p?p.sizes:'');openOv('ov-product');} function editProd(id){openProdForm(id);} function autoFillBout(){var t=DB.traders.find(function(x){return x.id===document.getElementById('p-trader').value;});var pb=document.getElementById('p-bout');if(t&&pb)pb.value=t.boutId;} function prevImg(inp){if(!inp.files||!inp.files[0])return;var r=new FileReader();r.onload=function(e){var prev=document.getElementById('p-img-prev');var hid=document.getElementById('p-img');if(prev)prev.innerHTML='';if(hid)hid.value=e.target.result;};r.readAsDataURL(inp.files[0]);} function clearImg(){var prev=document.getElementById('p-img-prev');var hid=document.getElementById('p-img');var fi=document.getElementById('p-img-file');if(prev)prev.innerHTML='📦';if(hid)hid.value='';if(fi)fi.value='';} function saveProd(){var id=document.getElementById('p-id').value;var name=document.getElementById('p-name').value.trim();if(!name){showToast('ادخل الاسم','er','حقل مطلوب');return;}var obj={id:id||'p'+Date.now(),sku:document.getElementById('p-sku').value||('SKU'+Date.now()),name:name,traderId:document.getElementById('p-trader').value,boutId:document.getElementById('p-bout').value,cost:parseFloat(document.getElementById('p-cost').value)||0,price:parseFloat(document.getElementById('p-price').value)||0,qty:parseInt(document.getElementById('p-qty').value)||0,cat:document.getElementById('p-cat').value.trim(),img:document.getElementById('p-img').value||'',notes:document.getElementById('p-notes').value.trim(),sizes:collectSizes()};if(id){var i=DB.products.findIndex(function(x){return x.id===id;});if(i>-1)DB.products[i]=obj;}else DB.products.push(obj);save();closeOv('ov-product');renderProducts();showToast('تم حفظ المنتج','ok');} function delProd(id){if(!confirm('حذف؟'))return; DB.products=DB.products.filter(function(p){return p.id!==id;});save();renderProducts();} function renderPos(){fillBouts();fillTraders('pos-t');var posT=document.getElementById('pos-t');if(posT){var opt=document.createElement('option');opt.value='';opt.textContent='جميع التاجرات';posT.insertBefore(opt,posT.firstChild);posT.value='';}renderPosGrid();renderCart();if(!activeStaffId&&(DB.staff||[]).length>0)openStaffSelector();} function renderPosGrid(){ var grid=document.getElementById('pos-grid');if(!grid)return; var bid=(document.getElementById('pos-b')||{}).value||'';var tid=(document.getElementById('pos-t')||{}).value||'';var q=((document.getElementById('pos-q')||{}).value||'').toLowerCase(); var list=DB.products.filter(function(p){if(p.qty<=0)return false;if(bid&&p.boutId!==bid)return false;if(tid&&p.traderId!==tid)return false;if(q&&p.name.toLowerCase().indexOf(q)<0&&p.sku.toLowerCase().indexOf(q)<0)return false;return true;}); if(!list.length){grid.innerHTML='
لا توجد منتجات
';return;} var html=''; for(var i=0;i'+(p.img?'':'
📦
')+'

'+p.name+'

'+(t?t.name:'')+'
'+fmtM(p.price)+'
متاح: '+p.qty+'
';} grid.innerHTML=html; } function posKey(e){if(e.key==='Enter'){var q=(document.getElementById('pos-q')||{}).value||'';var match=DB.products.find(function(p){return p.sku===q||p.sku===q.replace(/^0+/,'');});if(match){addToCart(match.id);document.getElementById('pos-q').value='';renderPosGrid();}}} function addToCart(pid){var p=DB.products.find(function(x){return x.id===pid;});if(!p||p.qty<=0)return;var ex=CART.find(function(c){return c.pid===pid;});if(ex){if(ex.qtymaxQty){ showToast('الكمية المتوفرة في المخزن: '+maxQty+' فقط','er'); ci.qty=maxQty; } else { ci.qty=Math.max(1,newQty); } renderCart();calcCart(); } function renderCart(){ var container=document.getElementById('cart-items');if(!container)return; if(!CART.length){container.innerHTML='
السلة فارغة
';return;} var html=''; for(var i=0;i'+(c.img?'':'
📦
')+'
'+c.name+'
'+fmt(c.price)+' x '+c.qty+'
'+c.qty+'
'+fmt(c.price*c.qty)+'
';} container.innerHTML=html; } function getDisc(sub){var t=(document.getElementById('disc-t')||{}).value||'0';var v=parseFloat((document.getElementById('disc-v')||{}).value)||0;if(t==='pct')return Math.min(sub,sub*v/100);if(t==='fixed')return Math.min(sub,v);return 0;} function calcCart(){var sub=CART.reduce(function(a,c){return a+c.price*c.qty;},0);var disc=getDisc(sub);var total=Math.max(0,sub-disc);var subEl=document.getElementById('s-sub');var dRow=document.getElementById('s-disc-row');var dEl=document.getElementById('s-disc');var totEl=document.getElementById('s-total');if(subEl)subEl.textContent=fmtM(sub);if(dRow)dRow.style.display=disc>0?'flex':'none';if(dEl)dEl.textContent='-'+fmtM(disc);if(totEl)totEl.textContent=fmtM(total);} function discChange(){var t=(document.getElementById('disc-t')||{}).value;var cr=document.getElementById('code-row');if(cr)cr.style.display=t==='code'?'block':'none';calcCart();} function applyCode(){var inp=document.getElementById('code-inp');var msg=document.getElementById('code-msg');if(!inp)return;var code=inp.value.trim().toUpperCase();var codes=DB.settings.codes||[];var gc=codes.find(function(c){return c.code===code&&c.active;});if(!gc){if(msg){msg.style.color='var(--er)';msg.textContent='الكود غير صالح';}return;}var dt=document.getElementById('disc-t');var dv=document.getElementById('disc-v');if(dt)dt.value=gc.type;if(dv)dv.value=gc.val;if(msg){msg.style.color='var(--ok)';msg.textContent='تم تطبيق: '+gc.label;}calcCart();} function startSale(){if(!CART.length){showToast('أضف منتجاً للسلة أولاً','warn','السلة فارغة');return;}document.getElementById('c-name').value='';document.getElementById('c-phone').value='';openOv('ov-customer');} function skipCust(){closeOv('ov-customer');finalizeSale('','');} function confirmCust(){var cn=(document.getElementById('c-name')||{}).value||'';var cp=(document.getElementById('c-phone')||{}).value||'';closeOv('ov-customer');finalizeSale(cn,cp);} function finalizeSale(cname,cphone){var sub=CART.reduce(function(a,c){return a+c.price*c.qty;},0);var disc=getDisc(sub);var total=Math.max(0,sub-disc);var method=(document.getElementById('pay-m')||{}).value||'cash';var boutId=CART[0]?CART[0].boutId:DB.curBout;var inv=nextInv();var items=CART.map(function(c){return{pid:c.pid,name:c.name,qty:c.qty,price:c.price,tid:c.tid};});var sale={id:'s'+Date.now(),boutId:boutId,inv:inv,date:nowDate(),time:nowTime(),method:method,items:items,sub:sub,disc:disc,total:total,cname:cname,cphone:cphone,status:'completed',staffId:activeStaffId||null};CART.forEach(function(c){var p=DB.products.find(function(x){return x.id===c.pid;});if(p)p.qty-=c.qty;});DB.sales.push(sale);save();LAST_SALE=sale;CART=[];renderCart();calcCart();renderPosGrid();showReceipt(sale);} function showReceipt(sale){var b=DB.boutiques.find(function(x){return x.id===sale.boutId;})||{};var mL={cash:'نقدا',card:'بطاقة',transfer:'تحويل'};document.getElementById('r-bname').textContent=b.name||'—';document.getElementById('r-bloc').textContent=b.loc||'';document.getElementById('r-dt').textContent=sale.date+' '+sale.time;document.getElementById('r-inv').textContent='فاتورة: '+sale.inv;var rc=document.getElementById('r-cust');if(rc){if(sale.cname||sale.cphone){rc.style.display='block';rc.innerHTML='العميل: '+(sale.cname||'')+''+(sale.cphone?' | +968'+sale.cphone:'');}else rc.style.display='none';}var ri=document.getElementById('r-items');if(ri){var html='';for(var i=0;i'+it.name+' x'+it.qty+''+fmtM(it.qty*it.price)+'';}ri.innerHTML=html;}var rs=document.getElementById('r-sum');if(rs){var s='';if(sale.disc>0)s+='
خصم-'+fmtM(sale.disc)+'
';s+='
الدفع'+(mL[sale.method]||sale.method)+'
';s+='
الاجمالي'+fmtM(sale.total)+'
';rs.innerHTML=s;}var rwa=document.getElementById('r-wa-btn');if(rwa)rwa.style.display=(sale.cphone&&sale.cphone.length>=7)?'block':'none';openOv('ov-receipt');} function sendReceiptWA(){if(!LAST_SALE)return;var s=LAST_SALE;var b=DB.boutiques.find(function(x){return x.id===s.boutId;})||{};var ph='968'+s.cphone.replace(/\D/g,'');var mL={cash:'نقدا',card:'بطاقة',transfer:'تحويل'};var lines=[b.name||'البوتيك','فاتورة: '+s.inv,'التاريخ: '+s.date,'---'];for(var i=0;i0)lines.push('خصم: -'+fmtM(s.disc));lines.push('الدفع: '+(mL[s.method]||s.method));lines.push('الاجمالي: '+fmtM(s.total));lines.push('شكرا لتسوقك معنا');window.open('https://wa.me/'+ph+'?text='+encodeURIComponent(lines.join('\n')),'_blank');} function newSale(){closeOv('ov-receipt');} function renderSales(){var tb=document.getElementById('tbl-sales');if(!tb)return;var fd=(document.getElementById('sales-date')||{}).value||'';var list=DB.sales.slice().reverse();if(fd)list=list.filter(function(s){return s.date===fd;});var mL={cash:'نقدا',card:'بطاقة',transfer:'تحويل'};var rows='';for(var i=0;i'+s.inv+''+s.date+' '+s.time+''+(s.cname||'')+''+fmtM(s.total)+''+(mL[s.method]||s.method)+''+(s.status==='completed'?'مكتملة':'مسترجعة')+'';}tb.innerHTML=rows||'لا توجد مبيعات';} function viewSale(id){var sale=DB.sales.find(function(x){return x.id===id;});if(!sale)return;VIEW_SALE=sale;var b=DB.boutiques.find(function(x){return x.id===sale.boutId;})||{};var mL={cash:'نقدا',card:'بطاقة',transfer:'تحويل'};var html='
'+(b.name||'')+'
'+sale.date+' '+sale.time+'
فاتورة: '+sale.inv+'
';if(sale.cname||sale.cphone)html+='
العميل: '+(sale.cname||'')+''+(sale.cphone?' | +968'+sale.cphone:'')+'
';html+='
';for(var i=0;i'+it.name+' x'+it.qty+''+fmtM(it.qty*it.price)+'';}html+='
';if(sale.disc>0)html+='
خصم-'+fmtM(sale.disc)+'
';html+='
الدفع'+(mL[sale.method]||sale.method)+'
';html+='
الاجمالي'+fmtM(sale.total)+'
';document.getElementById('sv-body').innerHTML=html;var svwa=document.getElementById('sv-wa');if(svwa)svwa.style.display=(sale.cphone&&sale.cphone.length>=7)?'block':'none';openOv('ov-sale-view');} function sendViewWA(){if(!VIEW_SALE)return;var s=VIEW_SALE;var b=DB.boutiques.find(function(x){return x.id===s.boutId;})||{};var ph='968'+(s.cphone||'').replace(/\D/g,'');var mL={cash:'نقدا',card:'بطاقة',transfer:'تحويل'};var lines=[b.name||'البوتيك','فاتورة: '+s.inv,'التاريخ: '+s.date,'---'];for(var i=0;i0)lines.push('خصم: -'+fmtM(s.disc));lines.push('الاجمالي: '+fmtM(s.total));window.open('https://wa.me/'+ph+'?text='+encodeURIComponent(lines.join('\n')),'_blank');} function refundSale(){if(!VIEW_SALE)return;var s=DB.sales.find(function(x){return x.id===VIEW_SALE.id;});if(!s||s.status==='refunded'){alert('تم الاسترجاع مسبقا');return;}if(!confirm('استرجاع هذه الفاتورة؟'))return; {s.status='refunded';s.items.forEach(function(it){var p=DB.products.find(function(x){return x.id===it.pid;});if(p)p.qty+=it.qty;});save();closeOv('ov-sale-view');renderSales();}} function renderSettlements(){var today=nowDate();var fromEl=document.getElementById('sf-from');var toEl=document.getElementById('sf-to');if(fromEl&&!fromEl.value)fromEl.value=today.slice(0,8)+'01';if(toEl&&!toEl.value)toEl.value=today;var from=fromEl?fromEl.value:'';var to=toEl?toEl.value:'';var cards=document.getElementById('settle-cards');if(cards){var html='';for(var i=0;i=from)&&(!to||s.date<=to)&&s.items.some(function(it){return it.tid===tr.id;});});var tsales=sales.reduce(function(a,s){return a+s.items.filter(function(it){return it.tid===tr.id;}).reduce(function(x,it){return x+it.qty*it.price;},0);},0);if(tsales===0)continue;var tcomm=tsales*comm/100;var tnet=tsales-tcomm;var tpaid=DB.settlements.filter(function(x){return x.traderId===tr.id&&(!from||x.date>=from)&&(!to||x.date<=to);}).reduce(function(a,x){return a+x.paid;},0);var trem=tnet-tpaid;var tid=tr.id;var bid=b.id||'';html+='
'+tr.name[0]+'
'+tr.name+'
'+(b.name||'')+'
'+(tr.phone?'':'')+'
مبيعاتها'+fmtM(tsales)+'
الايجار '+comm+'%'+fmtM(tcomm)+'
تم صرفه'+fmtM(tpaid)+'
المستحق لها'+fmtM(trem)+'
';}cards.innerHTML=html||'
لا توجد مبيعات في هذه الفترة
';}var tb=document.getElementById('tbl-settle');if(tb){var rows='';var list=DB.settlements.slice().reverse();for(var j=0;j
'+(str.name?str.name[0]:'?')+'
'+(str.name||'—')+'
'+(stb.name||'—')+''+st.date+''+fmtM(st.paid)+''+(st.notes||'—')+'';}tb.innerHTML=rows||'لا توجد دفعات';}} function recordPay(tid,bid){var el=document.getElementById('pamt-'+tid);var amt=el?parseFloat(el.value):0;if(!amt||amt<=0){showToast('أدخل مبلغ الدفعة','er','حقل مطلوب');return;}DB.settlements.push({id:'set'+Date.now(),traderId:tid,boutiqueId:bid,date:nowDate(),paid:amt,notes:'دفعة '+nowDate()});save();if(el)el.value='';renderSettlements();} function sendSettleWA(tid,from,to){var tr=DB.traders.find(function(x){return x.id===tid;});if(!tr||!tr.phone)return;var b=DB.boutiques.find(function(x){return x.id===tr.boutId;})||{};var comm=b.comm||0;var sales=DB.sales.filter(function(s){return s.status==='completed'&&(!from||s.date>=from)&&(!to||s.date<=to)&&s.items.some(function(it){return it.tid===tid;});});var tsales=sales.reduce(function(a,s){return a+s.items.filter(function(it){return it.tid===tid;}).reduce(function(x,it){return x+it.qty*it.price;},0);},0);var tcomm=tsales*comm/100;var tnet=tsales-tcomm;var tpaid=DB.settlements.filter(function(x){return x.traderId===tid&&(!from||x.date>=from)&&(!to||x.date<=to);}).reduce(function(a,x){return a+x.paid;},0);var trem=tnet-tpaid;var ph=tr.phone.replace(/\D/g,'');if(ph.indexOf('968')!==0)ph='968'+ph.replace(/^0/,'');var lines=['تسوية حساب - '+(b.name||''),'التاجرة: '+tr.name,'الفترة: '+(from||'')+' الى '+(to||''),'---','مبيعاتك: '+fmtM(tsales),'الايجار '+comm+'%: '+fmtM(tcomm),'الصافي لك: '+fmtM(tnet),(tpaid>0?'تم صرفه: '+fmtM(tpaid):''),'المتبقي: '+fmtM(trem),'---','شكرا لتعاملك معنا'].filter(function(l){return l!=='';});window.open('https://wa.me/'+ph+'?text='+encodeURIComponent(lines.join('\n')),'_blank');} function setStaffPeriod(p){ var t=nowDate(),f=''; if(p==='month') f=t.slice(0,8)+'01'; var fe=document.getElementById('st-from'); var te=document.getElementById('st-to'); if(fe)fe.value=f; if(te)te.value=t; renderStaffStats(); } function calcStaffComm(staff,sales){ if(!staff.ct||staff.ct==='none') return 0; var total=0; sales.forEach(function(s){ if(staff.ct==='pct'||staff.ct==='both') total+=s.total*(staff.cp||0)/100; if(staff.ct==='fixed'||staff.ct==='both') total+=(staff.cf||0)*s.items.length; }); return total; } function renderStaff(){ var tb=document.getElementById("tbl-staff"); if(!tb)return; var list=DB.staff||[]; var rows=""; for(var i=0;i'+s.name+""; rows+=""+s.email+""; rows+=""+(s.join||"—")+(s.end?'
انتهت: '+s.end+"
":"")+""; rows+=""+fmtM(s.salary||0)+""; rows+=""+cl+""; rows+=''+((s.perms||[]).length)+" صلاحية"; rows+=""; rows+=' '; rows+=''; rows+=""; } tb.innerHTML=rows||'لا توجد موظفات'; renderStaffStats(); } function openStaffForm(id){var s=id?((DB.staff||[]).find(function(x){return x.id===id;})):null;document.getElementById('st-title').textContent=s?'تعديل الموظفة':'اضافة موظفة';document.getElementById('st-id').value=s?s.id:'';document.getElementById('st-name').value=s?s.name:'';document.getElementById('st-email').value=s?(s.email||''):'';document.getElementById('st-pass').value='';document.getElementById('st-salary').value=s?(s.salary||0):0;document.getElementById('st-join').value=s?(s.join||nowDate()):nowDate();document.getElementById('st-end').value=s?(s.end||''):'';document.getElementById('st-ct').value=s?(s.ct||'none'):'none';document.getElementById('st-cp').value=s?(s.cp||0):0;document.getElementById('st-cf').value=s?(s.cf||0):0;commTypeChg();var pg=document.getElementById('perms-grid');if(pg){var ph='';for(var i=0;i-1))?'checked':'';ph+='';}pg.innerHTML=ph;}openOv('ov-staff');} function editStaff(id){openStaffForm(id);} function commTypeChg(){var t=(document.getElementById('st-ct')||{}).value;var cp=document.getElementById('st-cp');var cf=document.getElementById('st-cf');if(cp)cp.style.display=(t==='pct'||t==='both')?'block':'none';if(cf)cf.style.display=(t==='fixed'||t==='both')?'block':'none';} function saveStaff(){var id=document.getElementById('st-id').value;var name=document.getElementById('st-name').value.trim();if(!name){showToast('ادخل الاسم','er','حقل مطلوب');return;}var pass=document.getElementById('st-pass').value;var existing=id?((DB.staff||[]).find(function(x){return x.id===id;})):null;var perms=[];var chks=document.querySelectorAll('#perms-grid input:checked');for(var i=0;i-1)DB.staff[i]=obj;else DB.staff.push(obj);save();closeOv('ov-staff');renderStaff();showToast('تم حفظ الموظفة','ok');} function delStaff(id){if(!confirm('حذف؟'))return; DB.staff=DB.staff.filter(function(x){return x.id!==id;});save();renderStaff();} function setRepPeriod(p) { var t = nowDate(); var f = ''; if (p === 'today') { f = t; } else if (p === 'week') { var d = new Date(); d.setDate(d.getDate()-6); f = d.toISOString().slice(0,10); } else if (p === 'month') { f = t.slice(0,8)+'01'; } else { f = ''; } var fe = document.getElementById('rep-from'); var te = document.getElementById('rep-to'); if (fe) fe.value = f; if (te) te.value = t; renderReports(); } function renderReports() { var from = (document.getElementById('rep-from')||{}).value||''; var to = (document.getElementById('rep-to')||{}).value||''; // Filter sales by period var sales = DB.sales.filter(function(s) { if (s.status !== 'completed') return false; if (from && s.date < from) return false; if (to && s.date > to) return false; return true; }); var totalRev = sales.reduce(function(a,s){return a+s.total;},0); var totalComm = sales.reduce(function(a,s){ var b = DB.boutiques.find(function(x){return x.id===s.boutId;})||{}; return a + s.total*(b.comm||0)/100; },0); var totalPaid = DB.settlements.reduce(function(a,x){return a+x.paid;},0); var totalDue = DB.traders.reduce(function(a,tr){ var b = DB.boutiques.find(function(x){return x.id===tr.boutId;})||{}; var ts= sales.filter(function(s){return s.items.some(function(it){return it.tid===tr.id;});}) .reduce(function(x,s){return x+s.items.filter(function(it){return it.tid===tr.id;}).reduce(function(y,it){return y+it.qty*it.price;},0);},0); var net=ts-ts*(b.comm||0)/100; var paid=DB.settlements.filter(function(x){return x.traderId===tr.id;}).reduce(function(x,y){return x+y.paid;},0); return a+Math.max(0,net-paid); },0); // KPI Cards var rs = document.getElementById('rep-stats'); if (rs) rs.innerHTML = '
اجمالي الإيرادات
'+fmtM(totalRev)+'
' +'
عمولة البوتيك
'+fmtM(totalComm)+'
' +'
المستحقات المتبقية
'+fmtM(totalDue)+'
' +'
عدد الفواتير
'+sales.length+'
'; // Daily sales chart renderDailyChart(sales, from, to); // Payment methods renderPaymentMethods(sales); // Traders detailed renderTraderReport(sales, from, to); // Top products renderTopProducts(sales); // Slow movers renderSlowMovers(sales); // Inventory renderInventory(); } function renderDailyChart(sales, from, to) { var chartEl = document.getElementById('rep-chart-days'); var labelsEl = document.getElementById('rep-chart-labels'); if (!chartEl) return; // Build last 14 days or period var days = []; var end = to || nowDate(); var start = from; if (!start) { var d = new Date(end); d.setDate(d.getDate()-13); start = d.toISOString().slice(0,10); } var cur = new Date(start); var endD = new Date(end); while (cur <= endD && days.length < 30) { days.push(cur.toISOString().slice(0,10)); cur.setDate(cur.getDate()+1); } var dayTotals = {}; days.forEach(function(d){ dayTotals[d]=0; }); sales.forEach(function(s){ if(dayTotals[s.date]!==undefined) dayTotals[s.date]+=s.total; }); var maxVal = Math.max.apply(null, days.map(function(d){return dayTotals[d];})) || 1; var html = ''; var labelHtml = ''; days.forEach(function(d) { var h = Math.max(4, Math.round((dayTotals[d]/maxVal)*100)); var hasVal = dayTotals[d] > 0; html += '
' +(hasVal?'
'+Math.round(dayTotals[d])+'
':'') +'
' +'
'; labelHtml += '
'+d.slice(8)+'
'; }); chartEl.innerHTML = html; if (labelsEl) labelsEl.innerHTML = labelHtml; } function renderPaymentMethods(sales) { var el = document.getElementById('rep-payment-methods'); if (!el) return; var methods = { cash:'نقدا', card:'بطاقة', transfer:'تحويل' }; var totals = { cash:0, card:0, transfer:0 }; var counts = { cash:0, card:0, transfer:0 }; sales.forEach(function(s) { if (totals[s.method] !== undefined) { totals[s.method]+=s.total; counts[s.method]++; } }); var grandTotal = sales.reduce(function(a,s){return a+s.total;},0) || 1; var colors = { cash:'var(--ok)', card:'var(--in)', transfer:'var(--gold)' }; var html = ''; ['cash','card','transfer'].forEach(function(m) { if (!totals[m]) return; var pct = Math.round(totals[m]/grandTotal*100); html += '
' +'
' +''+methods[m]+''+fmtM(totals[m])+' ('+pct+'%)
' +'
' +'
'+counts[m]+' فاتورة
' +'
'; }); el.innerHTML = html || '
لا توجد مبيعات
'; } function renderTraderReport(sales, from, to) { var tb = document.getElementById('rep-traders'); if (!tb) return; var rows = ''; var traderData = DB.traders.map(function(tr) { var b = DB.boutiques.find(function(x){return x.id===tr.boutId;})||{}; var comm = b.comm||0; var trSales = sales.filter(function(s){return s.items.some(function(it){return it.tid===tr.id;});}); var items = trSales.reduce(function(a,s){return a+s.items.filter(function(it){return it.tid===tr.id;}).reduce(function(x,it){return x+it.qty;},0);},0); var revenue = trSales.reduce(function(a,s){return a+s.items.filter(function(it){return it.tid===tr.id;}).reduce(function(x,it){return x+it.qty*it.price;},0);},0); var boutComm = revenue*comm/100; var net = revenue-boutComm; var paid = DB.settlements.filter(function(x){return x.traderId===tr.id;}).reduce(function(a,x){return a+x.paid;},0); return {tr:tr, items:items, revenue:revenue, boutComm:boutComm, net:net, paid:paid, rem:net-paid}; }).filter(function(x){return x.revenue>0;}).sort(function(a,b){return b.revenue-a.revenue;}); traderData.forEach(function(x) { rows += '' +'
'+x.tr.name[0]+'
'+x.tr.name+'
' +''+x.items+'' +''+fmtM(x.revenue)+'' +''+fmtM(x.boutComm)+'' +''+fmtM(x.net)+'' +''+fmtM(x.paid)+'' +''+fmtM(x.rem)+'' +''; }); tb.innerHTML = rows || 'لا توجد بيانات'; } function renderTopProducts(sales) { var tb = document.getElementById('rep-top-prods'); if (!tb) return; var prodMap = {}; sales.forEach(function(s) { s.items.forEach(function(it) { if (!prodMap[it.pid]) prodMap[it.pid] = {name:it.name, tid:it.tid, qty:0, rev:0}; prodMap[it.pid].qty += it.qty; prodMap[it.pid].rev += it.qty*it.price; }); }); var sorted = Object.keys(prodMap).map(function(k){return prodMap[k];}).sort(function(a,b){return b.qty-a.qty;}).slice(0,10); var rows = ''; sorted.forEach(function(p, i) { var tr = DB.traders.find(function(x){return x.id===p.tid;})||{}; rows += '' +''+(i+1)+''+p.name+'' +''+(tr.name||'—')+'' +''+p.qty+'' +''+fmtM(p.rev)+'' +''; }); tb.innerHTML = rows || 'لا توجد بيانات'; } function renderSlowMovers(sales) { var tb = document.getElementById('rep-slow-prods'); var cnt = document.getElementById('rep-slow-count'); if (!tb) return; // Products with qty > 0 that had zero sales in the period var soldPids = {}; sales.forEach(function(s){s.items.forEach(function(it){soldPids[it.pid]=true;});}); var slow = DB.products.filter(function(p){return p.qty>0 && !soldPids[p.id];}); if (cnt) cnt.textContent = slow.length + ' منتج'; var rows = ''; slow.sort(function(a,b){return b.qty*b.price - a.qty*a.price;}).slice(0,15).forEach(function(p) { var tr = DB.traders.find(function(x){return x.id===p.traderId;})||{}; rows += '' +''+p.name+'' +''+(tr.name||'—')+'' +''+p.qty+'' +''+fmtM(p.price)+'' +''+fmtM(p.qty*p.price)+'' +''; }); tb.innerHTML = rows || 'جميع المنتجات تتحرك'; } function renderInventory() { var invEl = document.getElementById('rep-inventory'); var tb = document.getElementById('rep-stock'); var active = DB.products.filter(function(p){return p.qty>0;}); var totalVal = active.reduce(function(a,p){return a+p.qty*p.price;},0); var totalCost= active.reduce(function(a,p){return a+p.qty*p.cost;},0); var totalQty = active.reduce(function(a,p){return a+p.qty;},0); if (invEl) invEl.innerHTML = '
إجمالي القطع'+totalQty+' قطعة
' +'
قيمة التكلفة'+fmtM(totalCost)+'
' +'
قيمة البيع'+fmtM(totalVal)+'
' +'
هامش الربح المتوقع'+fmtM(totalVal-totalCost)+'
'; if (!tb) return; var rows = ''; active.sort(function(a,b){return b.qty*b.price-a.qty*a.price;}).slice(0,15).forEach(function(p) { rows += '' +''+p.name+'' +''+p.qty+'' +''+fmtM(p.qty*p.price)+'' +''; }); tb.innerHTML = rows || 'لا يوجد مخزون'; } function renderSettings(){var b=DB.boutiques&&DB.boutiques[0];var bn=document.getElementById('cfg-bname');var bl=document.getElementById('cfg-bloc');var bp=document.getElementById('cfg-bphone');var bc=document.getElementById('cfg-bcomm');if(b){if(bn)bn.value=b.name||'';if(bl)bl.value=b.loc||'';if(bp)bp.value=b.phone||'';if(bc)bc.value=b.comm||0;}var cc=document.getElementById('cfg-curr');if(cc&&DB.settings)cc.value=DB.settings.currency||'OMR';var vEl=document.getElementById('cfg-vat');if(vEl&&DB.settings)vEl.value=DB.settings.vat||0;var fEl=document.getElementById('cfg-card-fee');if(fEl&&DB.settings)fEl.value=DB.settings.cardFee||0;renderRates();renderCodes();var saEl=document.getElementById('cfg-stock-alert');if(saEl&&DB.settings)saEl.value=DB.settings.stockAlert||5;var snEl=document.getElementById('cfg-stock-notify');if(snEl&&DB.settings)snEl.checked=DB.settings.stockNotify!==false;var tpEl=document.getElementById('cfg-tax-pct');if(tpEl&&DB.settings)tpEl.value=DB.settings.vat||0;var txWho=DB.settings&&DB.settings.taxWho||'boutique';var twEl=document.getElementById('tax-'+txWho);if(twEl)twEl.checked=true;var ak=document.getElementById('cfg-apikey');if(ak&&DB.settings&&DB.settings.apiKey)ak.value=DB.settings.apiKey;var hcEl=document.getElementById('cfg-hide-cost');if(hcEl&&DB.settings)hcEl.checked=DB.settings.hideCost||false;applyCostVisibility();} function renderRates(){var el=document.getElementById('rates-list');if(!el||!DB.settings)return;var r=DB.settings.rates||{};var names={USD:'دولار',AED:'درهم',SAR:'ريال سعودي',EUR:'يورو',GBP:'جنيه',KWD:'دينار كويتي'};var html='';var keys=Object.keys(r);for(var i=0;i'+(names[k]||k)+'1 '+sym()+' = '+r[k].toFixed(4)+' '+k+'';}el.innerHTML=html||'
لا توجد اسعار
';} function saveCurr(){var cc=document.getElementById('cfg-curr');if(!cc)return;if(!DB.settings)DB.settings={};DB.settings.currency=cc.value;var syms={OMR:'ر.ع',SAR:'ر.س',AED:'د.ا',USD:'$',EUR:'€',GBP:'£',KWD:'د.ك'};DB.settings.sym=syms[cc.value]||cc.value;var vEl=document.getElementById('cfg-vat');var fEl=document.getElementById('cfg-card-fee');DB.settings.vat=vEl?parseFloat(vEl.value)||0:0;DB.settings.cardFee=fEl?parseFloat(fEl.value)||0:0;save();showToast('تم الحفظ بنجاح','ok');} function fetchRates(){var btn=document.getElementById('btn-rates');var st=document.getElementById('rates-st');if(btn)btn.textContent='جاري التحديث...';var base=(DB.settings&&DB.settings.currency)||'OMR';fetch('https://open.er-api.com/v6/latest/'+base).then(function(r){return r.json();}).then(function(data){if(data.result==='success'&&data.rates){if(!DB.settings)DB.settings={};var need=['USD','AED','SAR','EUR','GBP','KWD'];DB.settings.rates={};for(var i=0;iلا توجد اكواد';return;}var html='';for(var i=0;i'+c.code+''+c.label+''+(c.type==='pct'?c.val+'%':fmtM(c.val))+'';}el.innerHTML=html;} function addCode(){var code=prompt('كود الخصم:');if(!code||!code.trim())return;var type=prompt('النوع: pct او fixed','pct');if(type!=='pct'&&type!=='fixed'){alert('نوع غير صالح');return;}var val=parseFloat(prompt(type==='pct'?'النسبة %:':'المبلغ:','10'));if(!val)return;var label=prompt('وصف:',code)||code;var maxU=parseInt(prompt('اقصى استخدامات (0 = لا محدود):','0')||'0');if(!DB.settings)DB.settings={};if(!DB.settings.codes)DB.settings.codes=[];DB.settings.codes.push({code:code.trim().toUpperCase(),type:type,val:val,label:label,uses:0,maxUses:maxU,active:true});save();renderCodes();} function delCode(i){if(!confirm('حذف؟'))return; if(DB.settings&&DB.settings.codes){DB.settings.codes.splice(i,1);save();renderCodes();}} function renderDashboard(){ fillBouts(); var today=nowDate(); var cur=DB.boutiques.find(function(b){return b.id===DB.curBout;})||DB.boutiques[0]; if(!cur)return; var bsales=DB.sales.filter(function(s){return s.boutId===cur.id&&s.status==='completed';}); var t_today=bsales.filter(function(s){return s.date===today;}).reduce(function(a,s){return a+s.total;},0); var t_all=bsales.reduce(function(a,s){return a+s.total;},0); var tc=DB.traders.filter(function(t){return t.boutId===cur.id;}).length; var due=DB.traders.filter(function(t){return t.boutId===cur.id;}).reduce(function(a,tr){var comm=cur.comm||0;var ts=DB.sales.filter(function(s){return s.status==='completed'&&s.boutId===cur.id&&s.items.some(function(it){return it.tid===tr.id;});}).reduce(function(x,s){return x+s.items.filter(function(it){return it.tid===tr.id;}).reduce(function(y,it){return y+it.qty*it.price;},0);},0);var net=ts-ts*comm/100;var paid=DB.settlements.filter(function(x){return x.traderId===tr.id;}).reduce(function(x,y){return x+y.paid;},0);return a+Math.max(0,net-paid);},0); var el; el=document.getElementById('d-today');if(el)el.textContent=fmtM(t_today); el=document.getElementById('d-total');if(el)el.textContent=fmtM(t_all); el=document.getElementById('d-tcount');if(el)el.textContent=tc; el=document.getElementById('d-due');if(el)el.textContent=fmtM(due); var ds=document.getElementById('d-sales-tbl'); if(ds){var recent=bsales.slice().reverse().slice(0,6);var rows='';for(var i=0;i'+s.inv+''+fmtM(s.total)+''+s.time+'';}ds.innerHTML=rows||'لا توجد مبيعات';} var dt=document.getElementById('d-traders-tbl'); if(dt){var tdata=DB.traders.filter(function(t){return t.boutId===cur.id;}).map(function(tr){var comm=cur.comm||0;var ts=bsales.filter(function(s){return s.items.some(function(it){return it.tid===tr.id;});}).reduce(function(a,s){return a+s.items.filter(function(it){return it.tid===tr.id;}).reduce(function(x,it){return x+it.qty*it.price;},0);},0);var net=ts-ts*comm/100;var paid=DB.settlements.filter(function(x){return x.traderId===tr.id;}).reduce(function(a,x){return a+x.paid;},0);return{tr:tr,ts:ts,rem:net-paid};}).sort(function(a,b){return b.ts-a.ts;});var rows2='';for(var j=0;j
'+x.tr.name[0]+'
'+x.tr.name+'
'+fmtM(x.ts)+''+fmtM(x.rem)+'';}dt.innerHTML=rows2||'—';} } // ═══════════════════════════════════════════ // AUTH — LOGIN / LOGOUT // ═══════════════════════════════════════════ var currentUser = null; function doLogin() { var user = (document.getElementById('login-user')||{}).value||''; var pass = (document.getElementById('login-pass')||{}).value||''; var errEl = document.getElementById('login-error'); if (!user.trim()) { if(errEl){errEl.style.display='block';errEl.textContent='ادخل اسم المستخدم';} return; } // Find staff member var staff = (DB.staff||[]).find(function(s){ return s.email === user.trim() && s.pass === pass; }); if (!staff) { if(errEl){errEl.style.display='block';errEl.textContent='اسم المستخدم أو كلمة المرور غير صحيحة';} // Shake animation var btn = document.querySelector('#login-screen .btn-gold'); if(btn){btn.style.transform='translateX(8px)';setTimeout(function(){btn.style.transform='translateX(-8px)';setTimeout(function(){btn.style.transform='';},100);},100);} return; } // Success currentUser = staff; activeStaffId = staff.id; // Hide login screen var ls = document.getElementById('login-screen'); if(ls) ls.style.display='none'; // Update sidebar user info updateUserBar(); // Apply permissions — hide nav items not in perms applyPermissions(staff.perms||[]); // Navigate to POS or dashboard var startPage = (staff.perms||[]).indexOf('نقطة البيع') > -1 ? 'pos' : 'dashboard'; var navEl = document.getElementById('nav-'+startPage); goPage(startPage, navEl); // Clear password field var passEl = document.getElementById('login-pass'); if(passEl) passEl.value=''; } function resetToDemo() { if (!confirm('سيتم حذف كل البيانات وإعادة ضبط النظام. متأكد؟')) return; localStorage.removeItem('bpro3'); location.reload(); } function doLogout() { if(!confirm('تسجيل خروج؟')) return; currentUser = null; activeStaffId = null; // Show all nav items again var navItems = document.querySelectorAll('.sb-a'); for(var i=0;i -1) ? '' : 'none'; }); } // Allow Enter key on login form document.addEventListener('keydown', function(e){ var ls = document.getElementById('login-screen'); if(ls && ls.style.display !== 'none' && e.key === 'Enter') doLogin(); }); // Active staff tracking var activeStaffId = null; function selectStaff(id) { activeStaffId = id; var nameEl = document.getElementById('pos-staff-name'); var avatarEl = document.getElementById('pos-staff-avatar'); if (id) { var s = (DB.staff||[]).find(function(x){return x.id===id;}); if (s) { if (nameEl) nameEl.textContent = s.name; if (avatarEl) { avatarEl.textContent = s.name[0]; avatarEl.style.background = 'linear-gradient(135deg,var(--gold2),var(--rose))'; } } } else { if (nameEl) nameEl.textContent = 'لم تُحدد بعد'; if (avatarEl) { avatarEl.textContent = '؟'; avatarEl.style.background = 'var(--s3)'; } } closeOv('ov-select-staff'); } function openStaffSelector() { var list = document.getElementById('staff-select-list'); if (!list) return; var staff = DB.staff||[]; if (!staff.length) { list.innerHTML = '
لا توجد موظفات
'; openOv('ov-select-staff'); return; } var html = ''; for (var i=0; i'; html += '
' + s.name[0] + '
'; html += '
'; html += '
' + s.name + '
'; html += '
' + s.email + '
'; html += '
'; if (isActive) html += ''; html += ''; } list.innerHTML = html; openOv('ov-select-staff'); } function getVAT(){ return parseFloat((DB.settings&&DB.settings.vat)||0)||0; } function getCardFee(){ return parseFloat((DB.settings&&DB.settings.cardFee)||0)||0; } // TRADER REPORT var _traderReportId = null; function setTrRepPeriod(p){ var t=nowDate(),f='',d=new Date(); if(p==='month'){f=t.slice(0,8)+'01';} else if(p==='last'){ d.setDate(0); var y=d.getFullYear(),m=String(d.getMonth()+1).padStart(2,'0'); f=y+'-'+m+'-01'; t=y+'-'+m+'-'+String(d.getDate()).padStart(2,'0'); } var fe=document.getElementById('tr-rep-from'); var te=document.getElementById('tr-rep-to'); if(fe)fe.value=f; if(te)te.value=t; buildTraderReport(); } function openTraderReport(tid){ _traderReportId=tid; var t=nowDate(),f=t.slice(0,8)+'01'; var fe=document.getElementById('tr-rep-from'); var te=document.getElementById('tr-rep-to'); if(fe)fe.value=f; if(te)te.value=t; buildTraderReport(); openOv('ov-trader-report'); } function buildTraderReport(){ var tid=_traderReportId; if(!tid)return; var tr=DB.traders.find(function(x){return x.id===tid;}); if(!tr)return; var b=DB.boutiques.find(function(x){return x.id===tr.boutId;})||{}; var comm=b.comm||0, vat=getVAT(), cFee=getCardFee(); var from=(document.getElementById('tr-rep-from')||{}).value||''; var to=(document.getElementById('tr-rep-to')||{}).value||''; var title=document.getElementById('tr-rep-title'); if(title)title.textContent='تقرير: '+tr.name; var sales=DB.sales.filter(function(s){ if(s.status!=='completed')return false; if(from&&s.dateto)return false; return s.items.some(function(it){return it.tid===tid;}); }); var totalItems=0,totalRevenue=0,cardSales=0,saleRows=''; sales.forEach(function(s){ var trItems=s.items.filter(function(it){return it.tid===tid;}); var trRev=trItems.reduce(function(a,it){return a+it.qty*it.price;},0); var trQty=trItems.reduce(function(a,it){return a+it.qty;},0); var trCardFee=(s.method==='card'&&cFee)?trRev*cFee/100:0; totalItems+=trQty; totalRevenue+=trRev; if(s.method==='card')cardSales+=trRev; var mL={cash:'نقدا',card:'بطاقة',transfer:'تحويل'}[s.method]||s.method; saleRows+='' +''+s.date+''+s.inv+'' +''+trItems.map(function(it){return it.name+' x'+it.qty;}).join(', ')+'' +''+fmtM(trRev)+'' +''+mL+'' +(trCardFee>0?'-'+fmtM(trCardFee)+'':'—') +''; }); var boutCommAmt=totalRevenue*comm/100; var vatAmt=vat?totalRevenue*vat/100:0; var cardFeeAmt=cFee?cardSales*cFee/100:0; var netDue=totalRevenue-boutCommAmt-vatAmt-cardFeeAmt; var settles=DB.settlements.filter(function(x){return x.traderId===tid&&(!from||x.date>=from)&&(!to||x.date<=to);}); var totalPaid=settles.reduce(function(a,x){return a+x.paid;},0); var remaining=netDue-totalPaid; var html=''; html+='
'; html+='
الفترة: '+(from||'من البداية')+' — '+(to||'حتى الآن')+'
'; html+='
'; html+='
اجمالي مبيعاتك
'+fmtM(totalRevenue)+'
'; html+='
عدد القطع
'+totalItems+'
'; html+='
'; html+='
'; html+='
تفاصيل الخصومات
'; html+='
اجمالي مبيعاتك'+fmtM(totalRevenue)+'
'; html+='
ايجار البوتيك ('+comm+'%)- '+fmtM(boutCommAmt)+'
'; if(vatAmt>0)html+='
ضريبة VAT ('+vat+'%)- '+fmtM(vatAmt)+'
'; if(cardFeeAmt>0)html+='
رسوم جهاز الدفع ('+cFee+'%)- '+fmtM(cardFeeAmt)+'
'; html+='
الصافي المستحق لك'+fmtM(netDue)+'
'; html+='
'; html+='
'; html+='
الدفعات المستلمة
'; if(settles.length){settles.forEach(function(x){html+='
'+x.date+(x.notes?' - '+x.notes:'')+''+fmtM(x.paid)+'
';});} else{html+='
لا توجد دفعات
';} html+='
المتبقي'+fmtM(remaining)+'
'; html+='
'; if(sales.length){ html+='
تفاصيل الفواتير ('+sales.length+')
'; html+='
'+saleRows+'
التاريخالفاتورةالبضاعةالمبلغالدفعرسوم الجهاز
'; } var body=document.getElementById('tr-rep-body'); if(body)body.innerHTML=html; window._lastTraderReport={trader:tr,boutique:b,from:from,to:to,totalRevenue:totalRevenue,totalItems:totalItems,boutCommAmt:boutCommAmt,vatAmt:vatAmt,cardFeeAmt:cardFeeAmt,netDue:netDue,totalPaid:totalPaid,remaining:remaining,comm:comm,vat:vat,cFee:cFee,cardSales:cardSales}; } function sendTraderReportWA(){ var r=window._lastTraderReport; if(!r||!r.trader.phone){alert('لا يوجد رقم جوال');return;} var ph=r.trader.phone.replace(/\D/g,''); if(ph.indexOf('968')!==0)ph='968'+ph.replace(/^0/,''); var lines=[ 'كشف حساب - '+(r.boutique.name||'البوتيك'), 'التاجرة: '+r.trader.name, 'الفترة: '+(r.from||'من البداية')+' الى '+(r.to||'الآن'), '---', 'اجمالي مبيعاتك: '+fmtM(r.totalRevenue), 'عدد القطع: '+r.totalItems, '---', 'ايجار البوتيك '+r.comm+'%: -'+fmtM(r.boutCommAmt) ]; if(r.vatAmt>0)lines.push('ضريبة VAT '+r.vat+'%: -'+fmtM(r.vatAmt)); if(r.cardFeeAmt>0)lines.push('رسوم جهاز الدفع '+r.cFee+'%: -'+fmtM(r.cardFeeAmt)); lines.push('---'); lines.push('الصافي المستحق لك: '+fmtM(r.netDue)); if(r.totalPaid>0)lines.push('تم استلامه: '+fmtM(r.totalPaid)); lines.push('المتبقي: '+fmtM(r.remaining)); lines.push('---'); lines.push('شكرا لتعاملك معنا'); window.open('https://wa.me/'+ph+'?text='+encodeURIComponent(lines.join('\n')),'_blank'); } // ═══════════════════════════════════════════ // SIZE FIELDS // ═══════════════════════════════════════════ var SIZE_TEMPLATES = { abaya: [{id:'length',label:'الطول (سم)'},{id:'chest',label:'الصدر (سم)'},{id:'shoulder',label:'الكتف (سم)'},{id:'sleeve',label:'الكم (سم)'},{id:'waist',label:'الخصر (سم)'},{id:'size_label',label:'المقاس (S/M/L/XL)'}], top: [{id:'chest',label:'الصدر (سم)'},{id:'shoulder',label:'الكتف (سم)'},{id:'length',label:'الطول (سم)'},{id:'sleeve',label:'الكم (سم)'},{id:'size_label',label:'المقاس'}], pants: [{id:'waist',label:'الخصر (سم)'},{id:'hips',label:'الورك (سم)'},{id:'length',label:'الطول (سم)'},{id:'size_label',label:'المقاس'}], scarf: [{id:'length',label:'الطول (سم)'},{id:'width',label:'العرض (سم)'},{id:'material',label:'الخامة'}], bag: [{id:'width',label:'العرض (سم)'},{id:'height',label:'الارتفاع (سم)'},{id:'depth',label:'العمق (سم)'},{id:'color',label:'اللون'}], shoes: [{id:'size_label',label:'المقاس'},{id:'color',label:'اللون'},{id:'material',label:'الخامة'}], accessory: [{id:'size_label',label:'المقاس/الحجم'},{id:'color',label:'اللون'},{id:'material',label:'الخامة'}], custom:[{id:'f1',label:'قياس 1'},{id:'f2',label:'قياس 2'},{id:'f3',label:'قياس 3'},{id:'f4',label:'قياس 4'},{id:'f5',label:'قياس 5'},{id:'f6',label:'قياس 6'}] }; var _aiResult = null; function buildSizeFields() { var type = (document.getElementById('size-type')||{}).value; var container = document.getElementById('size-fields'); if (!container) return; if (!type) { container.innerHTML = ''; return; } var fields = SIZE_TEMPLATES[type] || []; // Load existing values if editing var existing = {}; try { existing = JSON.parse((document.getElementById('p-sizes')||{}).value||'{}'); } catch(e) {} var html = ''; for (var i=0; i'; html += ''; html += ''; } container.innerHTML = html; } function collectSizes() { var type = (document.getElementById('size-type')||{}).value; if (!type) return ''; var fields = SIZE_TEMPLATES[type] || []; var obj = { _type: type }; for (var i=0; i -1) continue; parts.push(obj[k]); } return parts.slice(0,3).join(' / '); } catch(e) { return ''; } } // ═══════════════════════════════════════════ // AI PRODUCT SCAN // ═══════════════════════════════════════════ function getApiKey() { return DB.settings && DB.settings.apiKey ? DB.settings.apiKey : ''; } function saveApiKey() { var key = (document.getElementById('cfg-apikey')||{}).value||''; if (!key.trim()) { alert('ادخل المفتاح'); return; } if (!DB.settings) DB.settings = {}; DB.settings.apiKey = key.trim(); save(); alert('تم حفظ المفتاح'); } function testApiKey() { var el = document.getElementById('api-test-result'); if (el) { el.style.color='var(--mu)'; el.textContent='جاري الاختبار...'; } var key = getApiKey(); if (!key) { if(el){el.style.color='var(--er)';el.textContent='لا يوجد مفتاح - احفظه اولا';} return; } fetch('https://api.anthropic.com/v1/messages', { method:'POST', headers:{'Content-Type':'application/json','x-api-key':key,'anthropic-version':'2023-06-01'}, body:JSON.stringify({model:'claude-haiku-4-5-20251001',max_tokens:20,messages:[{role:'user',content:'قل نعم فقط'}]}) }).then(function(r){return r.json();}).then(function(d){ if(d.content&&d.content[0]){if(el){el.style.color='var(--ok)';el.textContent='المفتاح يعمل';}} else{if(el){el.style.color='var(--er)';el.textContent='خطأ: '+(d.error&&d.error.message||'غير معروف');}} }).catch(function(e){if(el){el.style.color='var(--er)';el.textContent='فشل الاتصال';}}); } function aiScanProduct(input) { if (!input.files || !input.files[0]) return; var key = getApiKey(); if (!key) { alert('اضف مفتاح Claude API في الاعدادات اولا'); return; } var statusEl = document.getElementById('ai-status'); var wrapEl = document.getElementById('ai-wrap'); var prevEl = document.getElementById('ai-prev'); var outEl = document.getElementById('ai-out'); var applyBtn = document.getElementById('ai-apply'); var btn = document.getElementById('ai-btn'); if(statusEl) { statusEl.style.color='var(--gold)'; statusEl.textContent='جاري قراءة الصورة...'; } if(btn) btn.disabled = true; var reader = new FileReader(); reader.onload = function(e) { var b64 = e.target.result.split(',')[1]; var mime = input.files[0].type || 'image/jpeg'; if(prevEl) { prevEl.src=e.target.result; } if(wrapEl) { wrapEl.style.display='block'; } if(outEl) { outEl.textContent='جاري التحليل...'; } // Get category from size-type if selected var sizeType = (document.getElementById('size-type')||{}).value || ''; var catHint = sizeType ? ' (نوع المنتج: ' + sizeType + ')' : ''; var prompt = 'انت خبير في الموضة والملابس. حلل هذه الصورة لمنتج في بوتيك'+catHint+'.' +' استخرج المعلومات التالية وأجب بهذا التنسيق فقط: ' +'الاسم: [اسم المنتج] | ' +'اللون: [الالوان] | ' +'الخامة: [نوع القماش] | ' +'المقاس: [المقاس ان كان واضحا] | ' +'الطول: [بالسم ان كان واضحا] | ' +'الصدر: [بالسم ان كان واضحا] | ' +'الوصف: [وصف مختصر] | ' +'السعر المقترح: [بالريال العماني] ' +'اذا لم تكن المعلومة واضحة اكتب: غير محدد'; fetch('https://api.anthropic.com/v1/messages', { method: 'POST', headers: { 'Content-Type':'application/json', 'x-api-key':key, 'anthropic-version':'2023-06-01' }, body: JSON.stringify({ model: 'claude-haiku-4-5-20251001', max_tokens: 400, messages: [{ role: 'user', content: [ { type:'image', source:{ type:'base64', media_type:mime, data:b64 } }, { type:'text', text:prompt } ] }] }) }) .then(function(r) { return r.json(); }) .then(function(d) { if(btn) btn.disabled = false; if (d.content && d.content[0] && d.content[0].text) { var text = d.content[0].text; _aiResult = parseAiResult(text); if(outEl) outEl.innerHTML = text.replace(/\n/g,'
').replace(/\|/g,'
'); if(applyBtn) applyBtn.style.display = 'inline-flex'; if(statusEl) { statusEl.style.color='var(--ok)'; statusEl.textContent='تم التحليل'; } } else { var errMsg = d.error ? d.error.message : 'غير معروف'; if(outEl) { outEl.style.color='var(--er)'; outEl.textContent='خطأ: '+errMsg; } if(statusEl) { statusEl.style.color='var(--er)'; statusEl.textContent='فشل'; } } }) .catch(function(e) { if(btn) btn.disabled = false; if(outEl) { outEl.style.color='var(--er)'; outEl.textContent='فشل الاتصال بـ Claude'; } if(statusEl) { statusEl.style.color='var(--er)'; statusEl.textContent='خطأ في الاتصال'; } }); }; reader.readAsDataURL(input.files[0]); } function parseAiResult(text) { var result = {}; var parts = text.indexOf('|')>-1 ? text.split('|') : text.split('\n'); for (var i=0; ito) return false; return true; }); // KPI cards var totalSal=list.reduce(function(a,s){return a+(s.salary||0);},0); var totalComm=list.reduce(function(a,s){ var ss=allSales.filter(function(x){return x.staffId===s.id;}); return a+calcStaffComm(s,ss); },0); var sc=document.getElementById('staff-stats-cards'); if(sc){ sc.innerHTML= '
عدد الموظفات
'+list.length+'
' +'
إجمالي الرواتب
'+fmtM(totalSal)+'
' +'
إجمالي العمولات
'+fmtM(totalComm)+'
' +'
إجمالي المستحقات
'+fmtM(totalSal+totalComm)+'
'; } // Performance table var perf=document.getElementById('tbl-staff-perf'); if(perf){ var rows=''; for(var i=0;ibestC){bestC=hmap[h];bestH=h+':00';}}); rows+='' +'
'+st.name[0]+'
'+st.name+'
' +''+ss.length+'' +''+fmtM(sTotal)+'' +''+fmtM(sComm)+'' +''+fmtM(st.salary||0)+'' +''+fmtM(sDue)+'' +''+bestH+'' +'' +''; } perf.innerHTML=rows||'لا توجد موظفات'; } // Peak hours chart var peakEl=document.getElementById('peak-chart'); var peakLbl=document.getElementById('peak-labels'); if(peakEl){ var hours={}; for(var h=8;h<=22;h++) hours[String(h).padStart(2,'0')]=0; allSales.forEach(function(x){ if(!x.time) return; var hk=x.time.slice(0,2); if(hours[hk]!==undefined) hours[hk]+=x.total; }); var maxH=Math.max.apply(null,Object.keys(hours).map(function(k){return hours[k];}))||1; var ch='',lb=''; Object.keys(hours).forEach(function(hk){ var val=hours[hk]; var ht=Math.max(2,Math.round(val/maxH*90)); ch+='
' +(val>0?'
'+Math.round(val)+'
':'') +'
' +'
'; lb+='
'+parseInt(hk)+'
'; }); peakEl.innerHTML=ch; if(peakLbl)peakLbl.innerHTML=lb; } // Staff comparison bars var cmp=document.getElementById('staff-compare'); if(cmp){ var data=[]; for(var j=0;j0;}).sort(function(a,b){return b.total-a.total;}); var maxT=data.length?data[0].total:1; var html=''; if(!data.length){ html='
ربط المبيعات بالموظفة يتم تلقائياً عند تسجيل الدخول قبل إتمام البيع
'; } else { data.forEach(function(x){ var pct=Math.round(x.total/maxT*100); html+='
' +'
' +''+x.name+''+fmtM(x.total)+' ('+x.count+' فاتورة)
' +'
' +'
' +'
'; }); } cmp.innerHTML=html; } } function saveBoutiqueSettings(){ var b = DB.boutiques && DB.boutiques[0]; if (!b) { b = {id:'b1', name:'', loc:'', phone:'', comm:20, notes:''}; if (!DB.boutiques) DB.boutiques = []; DB.boutiques[0] = b; } var bn = document.getElementById('cfg-bname'); var bl = document.getElementById('cfg-bloc'); var bp = document.getElementById('cfg-bphone'); var bc = document.getElementById('cfg-bcomm'); if(bn) b.name = bn.value.trim(); if(bl) b.loc = bl.value.trim(); if(bp) b.phone = bp.value.trim(); if(bc) b.comm = parseFloat(bc.value)||0; DB.curBout = b.id; save(); fillBouts(); alert('تم حفظ بيانات البوتيك'); } // ═══════════════════════════════════════════ // THEME SYSTEM // ═══════════════════════════════════════════ function applyTheme(theme) { var body = document.body; var themes = ['theme-rose','theme-ocean','theme-forest','theme-purple','theme-light']; themes.forEach(function(t){ body.classList.remove(t); }); if (theme) body.classList.add(theme); if (!DB.settings) DB.settings = {}; DB.settings.theme = theme; save(); // Update active border on theme buttons var btns = document.querySelectorAll('.theme-btn'); for (var i=0;i 0 && p.qty <= threshold; }); if (!low.length) return; var existing = document.getElementById('stock-alert-banner'); if (existing) existing.remove(); var banner = document.createElement('div'); banner.id = 'stock-alert-banner'; banner.style.cssText = 'position:fixed;top:14px;left:50%;transform:translateX(-50%);background:rgba(224,92,92,.95);border-radius:10px;padding:12px 18px;z-index:8000;display:flex;align-items:center;gap:10px;font-size:13px;color:#fff;box-shadow:0 4px 20px rgba(0,0,0,.3);max-width:400px'; banner.innerHTML = '⚠️' + '
تنبيه مخزون منخفض
' + '
' + low.length + ' منتج وصل للحد الأدنى (' + threshold + ' قطع)
' + '' + ''; document.body.appendChild(banner); setTimeout(function(){ if(banner.parentElement) banner.remove(); }, 8000); } function showLowStock() { var threshold = parseInt((DB.settings||{}).stockAlert || 5); var low = DB.products.filter(function(p){ return p.qty > 0 && p.qty <= threshold; }); var msg = 'منتجات توشك النفاد:\n'; low.forEach(function(p){ var t = DB.traders.find(function(x){return x.id===p.traderId;})||{}; msg += '• ' + p.name + ' (' + (t.name||'') + ') — متبقي: ' + p.qty + '\n'; }); alert(msg); } function saveStockSettings() { if (!DB.settings) DB.settings = {}; var el = document.getElementById('cfg-stock-alert'); var chk = document.getElementById('cfg-stock-notify'); DB.settings.stockAlert = el ? parseInt(el.value)||5 : 5; DB.settings.stockNotify = chk ? chk.checked : true; save(); showToast('تم حفظ إعدادات التنبيه', 'ok'); checkStockAlerts(); } function saveTaxSettings() { if (!DB.settings) DB.settings = {}; var who = document.querySelector('input[name="tax-who"]:checked'); var pct = document.getElementById('cfg-tax-pct'); DB.settings.taxWho = who ? who.value : 'boutique'; DB.settings.vat = pct ? parseFloat(pct.value)||0 : 0; save(); showToast('تم حفظ إعدادات الضريبة', 'ok'); } // ═══════════════════════════════════════════ // TRADER COLOR + LOGO // ═══════════════════════════════════════════ function setTraderColor(color) { var inp = document.getElementById('t-color'); var prev = document.getElementById('t-color-preview'); if (inp) inp.value = color; if (prev) prev.style.background = color; } function prevTraderLogo(inp) { if (!inp.files || !inp.files[0]) return; var reader = new FileReader(); reader.onload = function(e) { var prev = document.getElementById('t-logo-prev'); var hid = document.getElementById('t-logo'); if (prev) prev.innerHTML = ''; if (hid) hid.value = e.target.result; }; reader.readAsDataURL(inp.files[0]); } function clearTraderLogo() { var prev = document.getElementById('t-logo-prev'); var hid = document.getElementById('t-logo'); var fi = document.getElementById('t-logo-file'); if (prev) prev.innerHTML = '💼'; if (hid) hid.value = ''; if (fi) fi.value = ''; } // ═══════════════════════════════════════════ // INIT // ═══════════════════════════════════════════ load(); // Ensure admin account always exists if (!DB.staff) DB.staff = []; var _hasAdmin = DB.staff.find(function(x){ return x.email === 'admin'; }); if (!_hasAdmin) { DB.staff.push({ id:'st1', name:'مدير النظام', email:'admin', pass:'admin123', salary:0, join:'2024-01-01', end:'', ct:'none', cp:0, cf:0, perms:['لوحة التحكم','نقطة البيع','البوتيكات','التاجرات','البضاعة', 'المبيعات','التسويات','الموظفات','التقارير','الاعدادات'], active:true }); save(); } // Ensure settings exist if (!DB.settings) { DB.settings = { currency:'OMR', sym:'ر.ع', rates:{USD:2.59,AED:0.706,SAR:0.691,EUR:2.80,GBP:3.26,KWD:0.122}, codes:[], vat:0, cardFee:0 }; save(); } fillBouts(); loadTheme(); checkStockAlerts(); applyCostVisibility(); applyCostVisibility(); var _sdEl = document.getElementById('sales-date'); if (_sdEl) _sdEl.value = nowDate(); // Focus login username var _uEl = document.getElementById('login-user'); if (_uEl) setTimeout(function(){ _uEl.focus(); }, 100); // Ensure settings exist if (!DB.settings) { DB.settings = { currency:'OMR', sym:'ر.ع', rates:{USD:2.59,AED:0.706,SAR:0.691,EUR:2.80,GBP:3.26,KWD:0.122}, codes:[], vat:0, cardFee:0 }; save(); } fillBouts(); loadTheme(); checkStockAlerts(); applyCostVisibility(); applyCostVisibility(); var _sdEl = document.getElementById('sales-date'); if (_sdEl) _sdEl.value = nowDate(); // Focus login username var _uEl = document.getElementById('login-user'); if (_uEl) setTimeout(function(){ _uEl.focus(); }, 100);load(); // Ensure admin account always exists if (!DB.staff) DB.staff = []; var _hasAdmin = DB.staff.find(function(x){ return x.email === 'admin'; }); if (!_hasAdmin) { DB.staff.push({ id:'st1', name:'مدير النظام', email:'admin', pass:'admin123', salary:0, join:'2024-01-01', end:'', ct:'none', cp:0, cf:0, perms:['لوحة التحكم','نقطة البيع','البوتيكات','التاجرات','البضاعة', 'المبيعات','التسويات','الموظفات','التقارير','الاعدادات'], active:true }); save(); } // Ensure settings exist if (!DB.settings) { DB.settings = { currency:'OMR', sym:'ر.ع', rates:{USD:2.59,AED:0.706,SAR:0.691,EUR:2.80,GBP:3.26,KWD:0.122}, codes:[], vat:0, cardFee:0 }; save(); } fillBouts(); loadTheme(); checkStockAlerts(); applyCostVisibility(); applyCostVisibility(); var _sdEl = document.getElementById('sales-date'); if (_sdEl) _sdEl.value = nowDate(); // Focus login username var _uEl = document.getElementById('login-user'); if (_uEl) setTimeout(function(){ _uEl.focus(); }, 100); // Ensure settings exist if (!DB.settings) { DB.settings = { currency:'OMR', sym:'ر.ع', rates:{USD:2.59,AED:0.706,SAR:0.691,EUR:2.80,GBP:3.26,KWD:0.122}, codes:[], vat:0, cardFee:0 }; save(); } fillBouts(); loadTheme(); checkStockAlerts(); applyCostVisibility(); applyCostVisibility(); var _sdEl = document.getElementById('sales-date'); if (_sdEl) _sdEl.value = nowDate(); // Focus login username var _uEl = document.getElementById('login-user'); if (_uEl) setTimeout(function(){ _uEl.focus(); }, 100); if (!DB.settings) { DB.settings = { currency:'OMR', sym:'ر.ع', rates:{USD:2.59,AED:0.706,SAR:0.691,EUR:2.80,GBP:3.26,KWD:0.122}, codes:[], vat:0, cardFee:0 }; save(); } fillBouts(); loadTheme(); checkStockAlerts(); applyCostVisibility(); applyCostVisibility(); var _sdEl = document.getElementById('sales-date'); if (_sdEl) _sdEl.value = nowDate(); // Focus login username var _uEl = document.getElementById('login-user'); if (_uEl) setTimeout(function(){ _uEl.focus(); }, 100); // Ensure settings exist if (!DB.settings) { DB.settings = { currency:'OMR', sym:'ر.ع', rates:{USD:2.59,AED:0.706,SAR:0.691,EUR:2.80,GBP:3.26,KWD:0.122}, codes:[], vat:0, cardFee:0 }; save(); } fillBouts(); loadTheme(); checkStockAlerts(); applyCostVisibility(); applyCostVisibility(); var _sdEl = document.getElementById('sales-date'); if (_sdEl) _sdEl.value = nowDate(); // Focus login username var _uEl = document.getElementById('login-user'); if (_uEl) setTimeout(function(){ _uEl.focus(); }, 100);load(); // Ensure admin account always exists if (!DB.staff) DB.staff = []; var _hasAdmin = DB.staff.find(function(x){ return x.email === 'admin'; }); if (!_hasAdmin) { DB.staff.push({ id:'st1', name:'مدير النظام', email:'admin', pass:'admin123', salary:0, join:'2024-01-01', end:'', ct:'none', cp:0, cf:0, perms:['لوحة التحكم','نقطة البيع','البوتيكات','التاجرات','البضاعة', 'المبيعات','التسويات','الموظفات','التقارير','الاعدادات'], active:true }); save(); } // Ensure settings exist if (!DB.settings) { DB.settings = { currency:'OMR', sym:'ر.ع', rates:{USD:2.59,AED:0.706,SAR:0.691,EUR:2.80,GBP:3.26,KWD:0.122}, codes:[], vat:0, cardFee:0 }; save(); } fillBouts(); loadTheme(); checkStockAlerts(); applyCostVisibility(); applyCostVisibility(); var _sdEl = document.getElementById('sales-date'); if (_sdEl) _sdEl.value = nowDate(); // Focus login username var _uEl = document.getElementById('login-user'); if (_uEl) setTimeout(function(){ _uEl.focus(); }, 100); // Ensure settings exist if (!DB.settings) { DB.settings = { currency:'OMR', sym:'ر.ع', rates:{USD:2.59,AED:0.706,SAR:0.691,EUR:2.80,GBP:3.26,KWD:0.122}, codes:[], vat:0, cardFee:0 }; save(); } fillBouts(); loadTheme(); checkStockAlerts(); applyCostVisibility(); applyCostVisibility(); var _sdEl = document.getElementById('sales-date'); if (_sdEl) _sdEl.value = nowDate(); // Focus login username var _uEl = document.getElementById('login-user'); if (_uEl) setTimeout(function(){ _uEl.focus(); }, 100);