feat(manager): ZOV factory status, room selector, order flow

This commit is contained in:
wasrusgen 2026-05-28 14:37:49 +03:00
parent 9403437b28
commit bf2ca464f8

View File

@ -256,7 +256,9 @@ window._managerOrders = window._managerOrders || [
{name:'Холодильник', wkey:'fridge', status:'wait', dims:'', brand:'', source:null},
],
techNote:'Ждём габариты духовки и посудомойки. Передано клиенту 10.05.',
blocker:'Техника: ждём 2 позиции' },
blocker:'Техника: ждём 2 позиции',
zovContract:'ЗОВ-25-041',
zovStatus:{code:'production',label:'В производстве',detail:'Корпуса готовы. Фасады в работе.',date:'27.05.2026 · 14:33',pct:45} },
{ id:2,client:'Петров В.Н.',phone:'+7 903 211-44-55',
type:'wardrobe',label:'Шкаф-купе · Пр. Мира 7, кв.18',
stage:4,contract:'МБ-2025-038',amount:94000,advance:47000,
@ -265,7 +267,9 @@ window._managerOrders = window._managerOrders || [
{label:'Аванс 1 · 50% при подписании',amount:47000,paid:true,date:'18.04.2025'},
{label:'Аванс 2 · при готовности к отгрузке',amount:47000,paid:false,date:null},
],
rooms:['Спальня'],tech:[],techNote:'',blocker:'Технолог: есть замечания' },
rooms:['Спальня'],tech:[],techNote:'',blocker:'Технолог: есть замечания',
zovContract:'ЗОВ-25-038',
zovStatus:{code:'ready',label:'Готов к отгрузке',detail:'Все позиции готовы. Дата доставки уточняется.',date:'26.05.2026 · 09:15',pct:90} },
{ id:3,client:'Сидорова М.К.',phone:'+7 916 888-22-11',
type:'kitchen',label:'Кухня · Ул. Садовая 5, кв.3',
stage:5,contract:'МБ-2025-029',amount:212000,advance:106000,
@ -274,9 +278,12 @@ window._managerOrders = window._managerOrders || [
{label:'Аванс 1 · 50% при подписании',amount:106000,paid:true,date:'10.03.2025'},
{label:'Аванс 2 · при готовности к отгрузке',amount:106000,paid:true,date:'08.05.2025'},
],
rooms:['Кухня','Балкон'],tech:[],techNote:'',blocker:null },
rooms:['Кухня','Балкон'],tech:[],techNote:'',blocker:null,
zovContract:'ЗОВ-25-029',
zovStatus:{code:'shipped',label:'Отгружен',detail:'Доставлен 09.05.2026. Договор закрыт.',date:'09.05.2026 · 11:20',pct:100} },
];
window._activeOrder = window._activeOrder || 0;
window._roomsEditing = false;
window._wiz = window._wiz || {type:null,step:0,answers:{},budget:null};
window._schedDay = window._schedDay || 3;
window._schedView = window._schedView || 'month';
@ -1077,7 +1084,11 @@ function _convertToOrder(oi) {
];
o.tech = [];
o.blocker = null;
o.rooms = [];
o.zovContract = '';
o.zovStatus = null;
window._activeOrder = oi;
window._roomsEditing = true;
document.getElementById('screen').innerHTML=renderScreen('manager_order');
document.getElementById('nav').innerHTML=navBar();
_toast('✅ Лид переведён в заказ '+o.contract,'var(--success)');
@ -2309,15 +2320,101 @@ function screenOrder() {
}
// Rooms
var roomHtml='<div class="section-label">Помещения</div><div class="card">'
+o.rooms.map(function(r){
return '<div class="row sb" style="padding:8px 0;border-bottom:1px solid rgba(0,0,0,.06)">'
+'<span style="font-size:14px;font-weight:600">🏠 '+r+'</span>'
+'<span class="badge green">✓ Замер получен</span></div>';
}).join('')+'</div>';
var oi = window._activeOrder;
var ALL_ROOMS=['Кухня','Гостиная','Спальня','Детская','Кабинет','Прихожая','Ванная','Балкон','Гардеробная','Столовая'];
var roomsEdit = window._roomsEditing;
var editSvg='<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5"><path d="M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7"/><path d="M18.5 2.5a2.121 2.121 0 0 1 3 3L12 15l-4 1 1-4 9.5-9.5z"/></svg>';
var roomHtml='<div class="section-label" style="display:flex;align-items:center;justify-content:space-between;padding-right:16px">'
+'<span>Помещения</span>'
+'<button onclick="window._roomsEditing=!window._roomsEditing;document.getElementById(\'screen\').innerHTML=renderScreen(\'manager_order\')" style="display:inline-flex;align-items:center;gap:4px;padding:3px 9px;border-radius:8px;border:1px solid rgba(0,62,126,.2);background:rgba(0,62,126,.06);color:var(--accent);font-size:11px;font-weight:700;cursor:pointer">'
+editSvg+(roomsEdit?' Готово':' Изменить')+'</button></div>';
if(roomsEdit){
// Chip selector
roomHtml+='<div class="card" style="padding:14px">'
+'<div style="font-size:12px;color:var(--muted);margin-bottom:10px">Выберите помещения, в которые идёт мебель:</div>'
+'<div style="display:flex;flex-wrap:wrap;gap:7px">';
ALL_ROOMS.forEach(function(r){
var sel = o.rooms.indexOf(r)>=0;
roomHtml+='<button onclick="_toggleRoom('+oi+',\''+r+'\')" style="padding:7px 13px;border-radius:20px;font-size:13px;font-weight:600;cursor:pointer;border:2px solid '+(sel?'var(--accent)':'#E2E8F0')+';background:'+(sel?'var(--accent)':'var(--card)')+';color:'+(sel?'#fff':'var(--muted)')+'">'+r+'</button>';
});
roomHtml+='</div>';
if(o.rooms.length){
roomHtml+='<div style="margin-top:10px;padding-top:10px;border-top:1px solid rgba(0,0,0,.07);font-size:12px;color:var(--muted)">Выбрано: <strong style="color:var(--ink)">'+o.rooms.join(', ')+'</strong></div>';
}
roomHtml+='</div>';
} else if(o.rooms.length){
roomHtml+='<div class="card">'
+o.rooms.map(function(r){
return '<div class="row sb" style="padding:8px 0;border-bottom:1px solid rgba(0,0,0,.06)">'
+'<span style="font-size:14px;font-weight:600">🏠 '+r+'</span>'
+'<span class="badge green">✓ Замер</span></div>';
}).join('')+'</div>';
} else {
roomHtml+='<div class="card" style="text-align:center;padding:18px;color:var(--muted)">'
+'<div style="font-size:22px;margin-bottom:6px">🏠</div>'
+'<div style="font-size:13px;font-weight:600">Помещения не указаны</div>'
+'<div style="font-size:12px;margin-top:3px">Нажмите «Изменить» чтобы добавить</div>'
+'</div>';
}
// ── ЗОВ — статус производства ────────────────────────────────────────────
var zovInfo = o.zovStatus ? _zovStatusInfo(o.zovStatus.code) : null;
var zovContractVal = o.zovContract || '';
var zovHtml = '<div class="section-label">Производство ЗОВ</div>'
+'<div class="card" style="padding:14px 16px">'
// ZOV contract number field
+'<div style="margin-bottom:12px">'
+'<div style="font-size:11px;font-weight:700;color:var(--muted);text-transform:uppercase;letter-spacing:.06em;margin-bottom:6px">Номер договора ЗОВ</div>'
+'<div style="display:flex;gap:8px;align-items:center">'
+'<input id="inp_zov_'+oi+'" type="text" value="'+zovContractVal+'" placeholder="Пр.: ЗОВ-26-001" onchange="_updateZovContract('+oi+',this.value)"'
+' style="flex:1;border:2px solid '+(zovContractVal?'var(--accent)':'#E2E8F0')+';border-radius:10px;padding:9px 12px;font-size:13px;font-weight:700;color:var(--ink);outline:none;background:var(--bg);font-family:monospace">'
+'<button onclick="_refreshZovStatus('+oi+')" style="padding:9px 13px;border-radius:10px;border:1.5px solid rgba(0,62,126,.25);background:rgba(0,62,126,.07);color:var(--accent);font-size:12px;font-weight:700;cursor:pointer;white-space:nowrap;flex-shrink:0">🔄 Статус</button>'
+'</div>'
+'</div>';
if(zovInfo && o.zovStatus){
var zst = o.zovStatus;
var zpct = zst.pct || 0;
zovHtml += '<div style="background:'+zovInfo.bg+';border-radius:11px;padding:12px 14px">'
+'<div style="display:flex;align-items:center;gap:9px;margin-bottom:8px">'
+'<span style="font-size:20px">'+zovInfo.icon+'</span>'
+'<div style="flex:1">'
+'<div style="font-size:14px;font-weight:700;color:'+zovInfo.color+'">'+zst.label+'</div>'
+'<div style="font-size:11px;color:var(--muted);margin-top:1px">'+zst.date+'</div>'
+'</div>'
+'<span style="font-size:15px;font-weight:900;color:'+zovInfo.color+'">'+zpct+'%</span>'
+'</div>'
// progress bar
+'<div style="height:6px;background:rgba(0,0,0,.08);border-radius:3px;margin-bottom:8px">'
+'<div style="height:6px;border-radius:3px;background:'+zovInfo.color+';width:'+zpct+'%"></div>'
+'</div>'
+'<div style="font-size:12px;color:var(--muted)">'+zst.detail+'</div>'
+'</div>';
// Pipeline steps for factory
var zSteps=[{c:'accepted',l:'Принят'},{c:'production',l:'Произв-во'},{c:'assembly',l:'Сборка'},{c:'ready',l:'Готов'},{c:'shipped',l:'Отгружен'}];
var zCodes=['accepted','production','assembly','ready','shipped'];
var zCurIdx = zCodes.indexOf(zst.code);
zovHtml += '<div style="display:flex;align-items:flex-start;padding:10px 0 2px;overflow-x:auto;scrollbar-width:none">';
zSteps.forEach(function(zs,zi){
var isDone = zi < zCurIdx;
var isAct = zi === zCurIdx;
var dotC = isDone?'#10B981':isAct?zovInfo.color:'#CBD5E1';
var dotBg = isDone?'#DCFCE7':isAct?zovInfo.bg:'var(--card)';
var dotTxt = isDone?'✓':(zi+1).toString();
if(zi>0) zovHtml+='<div style="flex:1;height:2px;background:'+(isDone?'#10B981':'#E2E8F0')+';margin-top:12px;min-width:6px"></div>';
zovHtml+='<div style="display:flex;flex-direction:column;align-items:center;gap:3px;flex-shrink:0;min-width:52px">'
+'<div style="width:26px;height:26px;border-radius:50%;border:2px solid '+dotC+';background:'+dotBg+';display:flex;align-items:center;justify-content:center;font-size:'+(isDone?'10':'9')+'px;font-weight:800;color:'+dotC+'">'+dotTxt+'</div>'
+'<div style="font-size:9px;font-weight:600;color:'+(isAct?zovInfo.color:'var(--muted)')+';text-align:center;line-height:1.2">'+zs.l+'</div>'
+'</div>';
});
zovHtml += '</div>';
} else {
zovHtml += '<div style="padding:10px 0 4px;font-size:12px;color:var(--muted);text-align:center">'
+(zovContractVal?'Нажмите «Статус» чтобы загрузить данные из zovofficial.com':'Введите номер договора ЗОВ из программы фабрики')
+'</div>';
}
zovHtml += '</div>';
// ── Расчёты (встроены в карточку) ─────────────────────────────────────────
var oi = window._activeOrder;
var advances = o.advances || [{label:'Аванс',amount:o.advance||0,paid:true,date:null}];
var paidSum = advances.reduce(function(s,a){return s+(a.paid?a.amount:0);},0);
var remaining= o.amount - paidSum;
@ -2390,7 +2487,7 @@ function screenOrder() {
+'</div>'
+'<div style="padding:14px 16px;background:var(--card);border-bottom:1px solid rgba(0,0,0,.06)">'
+'<div class="pipeline">'+pip+'</div></div>'
+'<div style="padding:16px">'+blk+techHtml+roomHtml+contHtml+'</div>'
+'<div style="padding:16px">'+blk+techHtml+roomHtml+zovHtml+contHtml+'</div>'
+'</div>';
}
function _startTech(){window._wizFromNav=false;window._wizScreen='manager_order';window._techSelection=window._techSelection||[];document.getElementById('screen').innerHTML=renderScreen('manager_tech');}
@ -2416,6 +2513,57 @@ function _confirmTech(){
},1000);
}
// ── ZOV Factory helpers ───────────────────────────────────────────────────────
function _zovStatusInfo(code){
var map={
'accepted': {color:'#2563EB',bg:'#EFF6FF', icon:'📋'},
'production':{color:'#D97706',bg:'#FFFBEB', icon:'⚙️'},
'assembly': {color:'#7C3AED',bg:'#F5F3FF', icon:'🔧'},
'ready': {color:'#059669',bg:'#F0FDF4', icon:'✅'},
'shipped': {color:'#0F766E',bg:'#F0FDFA', icon:'🚚'}
};
return map[code]||{color:'#8A94A6',bg:'#F9FAFB',icon:'❓'};
}
function _updateZovContract(oi,val){
window._managerOrders[oi].zovContract=val;
var inp=document.getElementById('inp_zov_'+oi);
if(inp) inp.style.borderColor=val?'var(--accent)':'#E2E8F0';
}
function _refreshZovStatus(oi){
var o=window._managerOrders[oi];
if(!o.zovContract){_toast('Введите номер договора ЗОВ','var(--warn)');return;}
_toast('🔄 Запрашиваю статус с zovofficial.com…','var(--accent)');
setTimeout(function(){
var codes=['accepted','production','assembly','ready','shipped'];
var curr=o.zovStatus?codes.indexOf(o.zovStatus.code):-1;
var next=codes[Math.min(curr+1,codes.length-1)];
var info=_zovStatusInfo(next);
var pcts={accepted:10,production:45,assembly:70,ready:90,shipped:100};
var details={
accepted:'Заявка принята фабрикой. Производство запланировано.',
production:'Корпуса готовы. Фасады и столешница в работе.',
assembly:'Все комплектующие готовы. Идёт финальная сборка.',
ready:'Готов к отгрузке. Согласуйте дату доставки.',
shipped:'Отгружен. Транспорт в пути.'
};
var now=new Date();
var d=String(now.getDate()).padStart(2,'0')+'.'+String(now.getMonth()+1).padStart(2,'0')+'.'+now.getFullYear();
var t=String(now.getHours()).padStart(2,'0')+':'+String(now.getMinutes()).padStart(2,'0');
o.zovStatus={code:next,label:info.icon+' '+['Принят','В производстве','Сборка','Готов к отгрузке','Отгружен'][codes.indexOf(next)],detail:details[next],date:d+' · '+t,pct:pcts[next]||0};
_toast('✅ Статус обновлён','var(--success)');
document.getElementById('screen').innerHTML=renderScreen('manager_order');
},1400);
}
// ── Rooms helpers ─────────────────────────────────────────────────────────────
function _toggleRoom(oi,room){
var o=window._managerOrders[oi];
var idx=o.rooms.indexOf(room);
if(idx>=0) o.rooms.splice(idx,1);
else o.rooms.push(room);
document.getElementById('screen').innerHTML=renderScreen('manager_order');
}
function _startOwnTech(key){
window._ownTechKey = key;
window._ownTechMode = 'choose';