diff --git a/public/app-runtime.js b/public/app-runtime.js
index 4af2845..23f849d 100644
--- a/public/app-runtime.js
+++ b/public/app-runtime.js
@@ -252,7 +252,7 @@ window.SUN_LEGACY_CATALOG_V175=[];
.sun-discount-panel label>span{display:block;color:#68717a;font-size:12px;margin-bottom:5px}
.sun-order-summary-discount{color:#8a5b00}
.sun-order-summary-net{font-weight:800;color:#15364c}
- .sun-order-summary-promo small{color:#7b858d;margin-left:5px}
+ .sun-order-summary-promo small{color:#7b858d;margin-left:5px}.sun-order-line-sum{display:flex;align-items:center;justify-content:flex-end;gap:8px}.sun-order-line-delete{width:28px;height:28px;flex:0 0 28px;border:1px solid #e2b8b8;border-radius:8px;background:#fff7f7;color:#a83535;font-size:19px;line-height:1;cursor:pointer}.sun-order-line-delete:hover{background:#ffeaea;border-color:#d98d8d}
.sun-doc-qr{width:92px;height:92px;object-fit:contain;border:1px solid #e0e3e5;border-radius:7px;padding:4px;background:#fff}
.sun-doc-title-with-qr{display:flex;align-items:flex-start;gap:14px;justify-content:flex-end}
.sun-doc-title-with-qr .sun-doc-title{text-align:right}
@@ -429,10 +429,11 @@ window.SUN_LEGACY_CATALOG_V175=[];
function renderOrderLines(){
if(!$('lines'))return;
if(!(draft.lines||[]).length){$('lines').innerHTML='
Выберите позиции из каталога.
';return}
- const rows=draft.lines.map((line,index)=>{const item=boxes.find(x=>String(x.id)===String(line.id));if(!item)return'';const qty=Math.max(1,Number(line.qty||1)),price=lineUnitPrice(line),isBox=[0,5,6].includes(Number(item.category||0));return ``}).join('');
+ const rows=draft.lines.map((line,index)=>{const item=boxes.find(x=>String(x.id)===String(line.id));if(!item)return'';const qty=Math.max(1,Number(line.qty||1)),price=lineUnitPrice(line),isBox=[0,5,6].includes(Number(item.category||0));return ``}).join('');
$('lines').innerHTML=`НаименованиеКол.ЦенаСтоимость
${rows}
Стоимость позиций${money(baseTotal(draft))}
`;
}
window.sunOrderLinePriceChanged=(index,input)=>{const line=draft.lines?.[index];if(!line)return;const value=Number(String(input.value||0).replace(',','.'));if(!Number.isFinite(value)){input.value=String(lineUnitPrice(line));return;}line.price=Math.max(0,Math.round(value*100)/100);const row=input.closest('.sun-order-line-row'),sum=row?.querySelector('.sun-order-line-sum b');if(sum)sum.textContent=money(line.price*Math.max(0,Number(line.qty||0)));const total=$('lines')?.querySelector('.sun-order-line-total b');if(total)total.textContent=money(baseTotal(draft));updateOrderSummary();};
+ window.sunRemoveOrderLine=(index)=>{if(!Array.isArray(draft.lines))return false;const i=Number(index);if(!Number.isInteger(i)||i<0||i>=draft.lines.length)return false;draft.lines.splice(i,1);renderCatalogV5();updateOrderSummary();return true;};
function boxNumber(item){const explicit=Number(item?.boxNumber);if(Number.isInteger(explicit)&&explicit>=0)return explicit;const name=String(item?.name||'');const match=name.match(/(?:бокс\s*)?№\s*0*(\d+)/i)||name.match(/^\s*№\s*0*(\d+)/i);return match?Number(match[1]):null}
function wantedBoxNumber(query){const raw=String(query||'').trim();if(!raw)return null;const match=raw.match(/^(?:бокс\s*)?(?:№\s*)?0*(\d+)\s*$/i);return match?Number(match[1]):null}
function itemMatches(item,query){if(!query)return true;if(Number(activeCat)===0){const wanted=wantedBoxNumber(query);return wanted!==null&&boxNumber(item)===wanted}const q=query.trim().toLowerCase();const parts=[item.name,item.catalogSection,item.weight,...(Array.isArray(item.composition)?item.composition:[]),...(Array.isArray(item.ingredients)?item.ingredients.map(x=>x?.[0]):[])];return parts.join(' ').toLowerCase().includes(q)}
@@ -659,16 +660,17 @@ window.SUN_LEGACY_CATALOG_V175=[];
function party(title,rows){const list=rows.filter(([,v])=>String(v||'').trim());if(!list.length)return'';return `${esc(title)}
${list.map(([k,v])=>`
${esc(k)}${esc(v)}
`).join('')}
`}
// ---------------- Order blank + compact receipt ----------------
+ function customerVisibleOrderNote(value){return String(value||'').split(/\r?\n/).filter(line=>{const text=line.trim();if(!text)return false;return !/^(?:заказ\s+из\s+telegram|импорт(?:ирован)?(?:о|ный)?\s+из\s+telegram|источник\s*[:—-]?\s*telegram|source\s*[:—-]?\s*telegram)\b/i.test(text)}).join('\n').trim()}
function currentRows(){return (draft.lines||[]).map((line,index)=>{const item=boxes.find(x=>String(x.id)===String(line.id)),price=lineUnitPrice(line),qty=Math.max(0,Number(line.qty||0)),categoryId=Number(item?.category??line.category??0);return{index:index+1,name:item?.name||line.name||`Позиция ${line.id||''}`,category:catName(categoryId),categoryId,weight:[0,5,6].includes(categoryId)?String(item?.weight||''):'',pieces:[0,5].includes(categoryId)?inferBoxPieces(item):0,price,qty,sum:price*qty}}).filter(r=>r.qty>0)}
const docDate=raw=>{if(!raw)return'—';const d=new Date(`${raw}T00:00:00`);return Number.isNaN(d.getTime())?raw:d.toLocaleDateString('ru-RU')};
const docActions=()=>``;
function showOrderBlank(){
- captureBuyerFromFields();captureDiscounts();const rows=currentRows(),p=pricing(draft),qr=defaultQr(),b=draft.buyerRequisites||buyerDefaults(),dialog=document.querySelector('#preview .dialog');if(!dialog)return;const number=draft.id||'черновик',qrNote=String(draft.blankQrText||'').trim();
- dialog.innerHTML=`})
${window.CateriumBranding.nameHTML()}${window.CateriumBranding.cityHTML()}
Заказ № ${esc(number)}
${esc($('event')?.value||'Новое мероприятие')}
${draft.status?`
${esc(draft.status)}`:''}
${qr?`

${esc(qrNote)}
`:''}
Клиент${esc($('contact')?.value||'—')}
Телефон${esc($('phone')?.value||'—')}
Дата и время выдачи${esc(docDate($('date')?.value))} · ${esc($('time')?.value||'—')}
Адрес доставки${esc($('address')?.value||'—')}
${b.name?`
Компания покупателя${esc(b.name)}
`:''}
| № | Позиция | Цена | Кол. | Сумма |
${rows.length?rows.map(r=>`| ${r.index} | ${esc(r.name)}${esc(r.category)}${(r.weight||r.pieces)?`${r.weight?`${r.categoryId===6?'Вес порции':'Вес бокса'}: ${esc(r.weight)}`:''}${r.weight&&r.pieces?' · ':''}${r.pieces?`Количество: ${esc(r.pieces)} шт.`:''}`:''} | ${money(r.price)} | ${r.qty} | ${money(r.sum)} |
`).join(''):'| В заказе пока нет позиций. |
'}
Стоимость позиций${money(p.base)}
${p.manual?`
Скидка− ${money(p.manual)}
`:''}${p.promo?`
Промокод ${esc(draft.promoCode||'')}− ${money(p.promo)}
`:''}
Доставка${money(p.delivery)}
Итого${money(p.total)}
Предоплата${money(p.paid)}
Остаток к оплате${money(p.balance)}
${$('note')?.value?`
Комментарий к заказу${esc($('note').value)}
`:''}${docActions()}
`;window.modal?.('preview');const noteEl=$('sunBlankQrText');if(noteEl){const save=()=>{const text=String(noteEl.innerText||noteEl.textContent||'').replace(/\u00a0/g,' ').trim();draft.blankQrText=text;if(draft.id){const saved=(orders||[]).find(o=>String(o.id)===String(draft.id));if(saved){saved.blankQrText=text;try{persist()}catch(_){}}}};noteEl.addEventListener('input',save);noteEl.addEventListener('blur',save);}
+ captureBuyerFromFields();captureDiscounts();const rows=currentRows(),p=pricing(draft),qr=defaultQr(),b=draft.buyerRequisites||buyerDefaults(),dialog=document.querySelector('#preview .dialog');if(!dialog)return;const number=draft.id||'черновик',qrNote=String(draft.blankQrText||'').trim(),visibleNote=customerVisibleOrderNote($('note')?.value);
+ dialog.innerHTML=`})
${window.CateriumBranding.nameHTML()}${window.CateriumBranding.cityHTML()}
Заказ № ${esc(number)}
${esc($('event')?.value||'Новое мероприятие')}
${draft.status?`
${esc(draft.status)}`:''}
${qr?`

${esc(qrNote)}
`:''}
Клиент${esc($('contact')?.value||'—')}
Телефон${esc($('phone')?.value||'—')}
Дата и время выдачи${esc(docDate($('date')?.value))} · ${esc($('time')?.value||'—')}
Адрес доставки${esc($('address')?.value||'—')}
${b.name?`
Компания покупателя${esc(b.name)}
`:''}
| № | Позиция | Цена | Кол. | Сумма |
${rows.length?rows.map(r=>`| ${r.index} | ${esc(r.name)}${esc(r.category)}${(r.weight||r.pieces)?`${r.weight?`${r.categoryId===6?'Вес порции':'Вес бокса'}: ${esc(r.weight)}`:''}${r.weight&&r.pieces?' · ':''}${r.pieces?`Количество: ${esc(r.pieces)} шт.`:''}`:''} | ${money(r.price)} | ${r.qty} | ${money(r.sum)} |
`).join(''):'| В заказе пока нет позиций. |
'}
Стоимость позиций${money(p.base)}
${p.manual?`
Скидка− ${money(p.manual)}
`:''}${p.promo?`
Промокод ${esc(draft.promoCode||'')}− ${money(p.promo)}
`:''}
Доставка${money(p.delivery)}
Итого${money(p.total)}
Предоплата${money(p.paid)}
Остаток к оплате${money(p.balance)}
${visibleNote?`
Комментарий к заказу${esc(visibleNote)}
`:''}${docActions()}
`;window.modal?.('preview');const noteEl=$('sunBlankQrText');if(noteEl){const save=()=>{const text=String(noteEl.innerText||noteEl.textContent||'').replace(/\u00a0/g,' ').trim();draft.blankQrText=text;if(draft.id){const saved=(orders||[]).find(o=>String(o.id)===String(draft.id));if(saved){saved.blankQrText=text;try{persist()}catch(_){}}}};noteEl.addEventListener('input',save);noteEl.addEventListener('blur',save);}
}
function showReceipt(){
- captureBuyerFromFields();captureDiscounts();const rows=currentRows(),p=pricing(draft),s=readSeller(),b=draft.buyerRequisites||buyerDefaults(),dialog=document.querySelector('#preview .dialog');if(!dialog)return;const seller=s.includeSeller!==false?party('Продавец',[['Наименование',s.sellerLegalName||s.sellerName],['ИНН',s.sellerInn],['КПП',s.sellerKpp],['ОГРН / ОГРНИП',s.sellerOgrn],['Адрес',s.sellerLegalAddress],['Телефон',s.sellerPhone],['E-mail',s.sellerEmail],['Банк',s.sellerBank],['БИК',s.sellerBik],['Расч. счёт',s.sellerAccount],['Корр. счёт',s.sellerCorrAccount]]):'';const buyer=party('Покупатель',[['Компания / ИП',b.name],['ИНН',b.inn],['КПП',b.kpp],['ОГРН / ОГРНИП',b.ogrn],['Адрес',b.legalAddress],['Контакт',b.contact],['Телефон',b.phone],['E-mail',b.email],['Банк',b.bank],['БИК',b.bik],['Расч. счёт',b.account],['Корр. счёт',b.corrAccount]]);
- dialog.innerHTML=`})
${esc(s.sellerName||(window.CateriumBranding.documentName()))}${esc(s.sellerLegalName||'')}
Товарный чек № ${esc(draft.id||'—')}
${esc(docDate($('date')?.value||draft.date))} · ${esc($('time')?.value||draft.time||'')}
${seller}${buyer}
| № | Наименование | Цена | Кол. | Сумма |
${rows.length?rows.map(r=>`| ${r.index} | ${esc(r.name)}${(r.weight||r.pieces)?`${r.weight?`${r.categoryId===6?'Вес порции':'Вес бокса'}: ${esc(r.weight)}`:''}${r.weight&&r.pieces?' · ':''}${r.pieces?`Количество: ${esc(r.pieces)} шт.`:''}`:''} | ${money(r.price)} | ${r.qty} | ${money(r.sum)} |
`).join(''):'| В заказе нет позиций. |
'}
Стоимость позиций${money(p.base)}
${p.manual?`
Скидка− ${money(p.manual)}
`:''}${p.promo?`
Промокод ${esc(draft.promoCode||'')}− ${money(p.promo)}
`:''}
Доставка${money(p.delivery)}
Итого${money(p.total)}
Оплачено${money(p.paid)}
К оплате${money(p.balance)}
${$('note')?.value?`
Примечание${esc($('note').value)}
`:''}${docActions()}
`;window.modal?.('preview');
+ captureBuyerFromFields();captureDiscounts();const rows=currentRows(),p=pricing(draft),s=readSeller(),b=draft.buyerRequisites||buyerDefaults(),dialog=document.querySelector('#preview .dialog'),visibleNote=customerVisibleOrderNote($('note')?.value);if(!dialog)return;const seller=s.includeSeller!==false?party('Продавец',[['Наименование',s.sellerLegalName||s.sellerName],['ИНН',s.sellerInn],['КПП',s.sellerKpp],['ОГРН / ОГРНИП',s.sellerOgrn],['Адрес',s.sellerLegalAddress],['Телефон',s.sellerPhone],['E-mail',s.sellerEmail],['Банк',s.sellerBank],['БИК',s.sellerBik],['Расч. счёт',s.sellerAccount],['Корр. счёт',s.sellerCorrAccount]]):'';const buyer=party('Покупатель',[['Компания / ИП',b.name],['ИНН',b.inn],['КПП',b.kpp],['ОГРН / ОГРНИП',b.ogrn],['Адрес',b.legalAddress],['Контакт',b.contact],['Телефон',b.phone],['E-mail',b.email],['Банк',b.bank],['БИК',b.bik],['Расч. счёт',b.account],['Корр. счёт',b.corrAccount]]);
+ dialog.innerHTML=`})
${esc(s.sellerName||(window.CateriumBranding.documentName()))}${esc(s.sellerLegalName||'')}
Товарный чек № ${esc(draft.id||'—')}
${esc(docDate($('date')?.value||draft.date))} · ${esc($('time')?.value||draft.time||'')}
${seller}${buyer}
| № | Наименование | Цена | Кол. | Сумма |
${rows.length?rows.map(r=>`| ${r.index} | ${esc(r.name)}${(r.weight||r.pieces)?`${r.weight?`${r.categoryId===6?'Вес порции':'Вес бокса'}: ${esc(r.weight)}`:''}${r.weight&&r.pieces?' · ':''}${r.pieces?`Количество: ${esc(r.pieces)} шт.`:''}`:''} | ${money(r.price)} | ${r.qty} | ${money(r.sum)} |
`).join(''):'| В заказе нет позиций. |
'}
Стоимость позиций${money(p.base)}
${p.manual?`
Скидка− ${money(p.manual)}
`:''}${p.promo?`
Промокод ${esc(draft.promoCode||'')}− ${money(p.promo)}
`:''}
Доставка${money(p.delivery)}
Итого${money(p.total)}
Оплачено${money(p.paid)}
К оплате${money(p.balance)}
${visibleNote?`
Примечание${esc(visibleNote)}
`:''}${docActions()}
`;window.modal?.('preview');
}
window.sunShowConfiguredReceipt=showReceipt;window.sunShowOrderBlankV5=showOrderBlank;
function patchDocButtons(){qa('#new .actions button').forEach(b=>{const text=(b.textContent||'').trim();if(text==='Товарный чек')b.onclick=showReceipt;if(text==='Бланк заказа')b.onclick=showOrderBlank;});}
@@ -4069,6 +4071,7 @@ window.SUN_LEGACY_CATALOG_V175=[];
try{window.renderStats?.()}catch(_){}
try{window.sunRenderOrderCards?.()}catch(_){}
window.dispatchEvent(new CustomEvent('sun:order-deleted',{detail:{id:order.id}}));
+ try{const sync=window.SunCloudV2?.syncNow?.();if(sync&&typeof sync.catch==='function')sync.catch(error=>console.warn('Order delete cloud sync failed',error));}catch(error){console.warn('Order delete cloud sync failed',error)}
window.SunEnterprise?.toast?.(`Заказ №${order.id} удалён.`,'success');
return true;
};