/* Модуль «Прайсы и тендер» — прайс работ: цена в нашем договоре с заказчиком против реальных заявок бригад/подрядчиков, маржа и причина разницы. Маржа/закупочные цифры видны только ролям с seeMargin/seeSupplierPrice. */ window.RD = window.RD || { core: {}, modules: {} }; window.RD.modules.Pricing = function Pricing() { var store = RD.core.useStore(); var C = RD.core, money = C.money0, h = React.createElement; var perms = store.perms; var wp = store.raw.workPrices || []; var flagMeta = { full: { label: 'всё включено', c: 'var(--rd-good)', bg: 'var(--rd-good-soft,#e7f4ec)' }, company: { label: 'СРО/НДС', c: '#0a7ea4', bg: '#e3f3f8' }, risk: { label: 'неполный объём', c: 'var(--rd-bad)', bg: 'var(--rd-bad-soft,#fbeaea)' } }; var canMargin = perms.seeMargin || perms.seeSupplierPrice || perms.admin; return h('div', { className: 'rd-main-content', style: { background: 'var(--rd-surface)', overflow: 'auto' } }, h('div', { style: { height: 46, flex: 'none', borderBottom: '1px solid var(--rd-border)', display: 'flex', alignItems: 'center', padding: '0 16px', gap: 12, background: 'var(--rd-surface-2)' } }, h('div', { style: { fontSize: 13, fontWeight: 600 } }, 'Прайсы и тендер'), h('div', { className: 'mono', style: { fontSize: 11.5, color: 'var(--rd-text-muted)' } }, wp.length + ' видов работ')), wp.length === 0 ? h('div', { style: { flex: 1, display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent: 'center', padding: 40, color: 'var(--rd-text-muted)' } }, h('div', { style: { fontSize: 48, marginBottom: 16, opacity: 0.3 } }, '💰'), h('div', { style: { fontSize: 18, fontWeight: 600, marginBottom: 8, color: 'var(--rd-text)' } }, 'Прайсинг не загружен'), h('div', { style: { fontSize: 13, marginBottom: 20, textAlign: 'center', maxWidth: 480 } }, 'Прайсы и тендер показывают цену в договоре с заказчиком против реальных заявок бригад/подрядчиков, маржу и причину разницы.'), h('div', { style: { fontSize: 12, color: 'var(--rd-text-muted)', textAlign: 'center', maxWidth: 480 } }, 'Данные загружаются из таблицы ops.pricing или аналогичной структуры в БД.') ) : h('div', { style: { padding: 16 } }, h('div', { style: { fontSize: 11.5, color: 'var(--rd-text-muted)', margin: '0 0 12px 2px', lineHeight: 1.5 } }, canMargin ? 'Цена в нашем договоре с заказчиком против реальных заявок. Маржа и причина разницы: что включено, что забыли или намеренно убрали, чтобы пройти тендер.' : 'Заявки подрядчиков по видам работ. Цены и маржа скрыты для вашей роли «' + perms.role + '».'), wp.map(function (w, wi) { return h('div', { key: wi, style: { border: '1px solid var(--rd-border)', borderRadius: 12, overflow: 'hidden', marginBottom: 14, background: 'var(--rd-surface)' } }, // шапка вида работ h('div', { style: { display: 'flex', alignItems: 'center', gap: 10, padding: '11px 15px', borderBottom: '1px solid var(--rd-border)', background: 'var(--rd-surface-3)' } }, h('span', { style: { fontSize: 13.5, fontWeight: 600 } }, w.name), h('span', { style: { fontSize: 11, color: 'var(--rd-text-muted)' } }, 'объём ' + w.vol + ' ' + w.unit), h('span', { style: { flex: 1 } }), canMargin ? h('span', { style: { fontSize: 11, color: 'var(--rd-text-muted)' } }, 'в договоре: ') : null, canMargin ? h('span', { className: 'mono', style: { fontSize: 14, fontWeight: 700, color: 'var(--rd-accent)' } }, money(w.our) + ' ₽/' + w.unit) : null), // заголовок таблицы заявок h('div', { style: { display: 'grid', gridTemplateColumns: '150px 96px 92px 96px minmax(140px,1fr) minmax(160px,1.2fr)', fontSize: 10, fontWeight: 600, color: 'var(--rd-text-muted)', background: 'var(--rd-surface-2)' } }, ['Исполнитель', 'Тип', 'Их цена', 'Маржа', 'Что включено', 'Почему такая цена'].map(function (t, i) { return h('div', { key: i, style: { padding: '7px 12px', textAlign: (i === 2 || i === 3) ? 'right' : 'left' } }, t); })), // заявки (w.bids || []).map(function (b, bi) { var margin = w.our - b.price, marginPct = Math.round(margin / w.our * 100), fm = flagMeta[b.flag] || flagMeta.full; return h('div', { key: bi, style: { display: 'grid', gridTemplateColumns: '150px 96px 92px 96px minmax(140px,1fr) minmax(160px,1.2fr)', alignItems: 'center', fontSize: 12, borderTop: '1px solid var(--rd-border)', background: b.flag === 'risk' ? 'rgba(207,59,59,.05)' : 'transparent' } }, h('div', { style: { padding: '9px 12px', fontWeight: 600 } }, b.who), h('div', { style: { padding: '9px 12px' } }, h('span', { style: { fontSize: 9.5, fontWeight: 700, color: fm.c, background: fm.bg, padding: '2px 7px', borderRadius: 11, whiteSpace: 'nowrap' } }, fm.label)), h('div', { className: 'mono', style: { padding: '9px 12px', textAlign: 'right', fontWeight: 600 } }, canMargin ? (money(b.price) + ' ₽') : '—'), h('div', { style: { padding: '9px 12px', textAlign: 'right' } }, canMargin ? h(React.Fragment, null, h('span', { className: 'mono', style: { fontWeight: 700, fontSize: 12, color: margin > 0 ? 'var(--rd-good)' : margin < 0 ? 'var(--rd-bad)' : 'var(--rd-text-muted)' } }, (margin >= 0 ? '+' : '') + money(margin)), h('span', { style: { display: 'block', fontSize: 9.5, color: 'var(--rd-text-muted)' } }, (margin >= 0 ? '+' : '') + marginPct + '% · ' + money(margin * w.vol) + ' ₽')) : '—'), h('div', { style: { padding: '9px 12px', fontSize: 11, color: 'var(--rd-text-2)' } }, b.incl), h('div', { style: { padding: '9px 12px', fontSize: 11, color: 'var(--rd-text-2)', lineHeight: 1.35 } }, b.reason) ); }) ); }) ) ); };