Compare commits

...

3 Commits

Author SHA1 Message Date
Тимур Городецкий abe7cdbbc3 fix(oid): рекомендованный поставщик зелёным, как в СТ
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-09-03 16:42:41 +05:00
Тимур Городецкий e50eca4fd4 fix(oid): статус СТ до оповещения — на финале согласования шлём Согласована
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-09-03 16:34:33 +05:00
Тимур Городецкий fa47373d57 fix(oid): подсказки поиска в диалоге замены не обрезаются
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-09-03 16:15:03 +05:00
4 changed files with 34 additions and 19 deletions
@@ -135,14 +135,14 @@
border-top: 3px solid $ok !important; border-top: 3px solid $ok !important;
} }
.thSupplierRec { .thSupplierRec {
background: $accent-bg !important; background: $ok-bg !important;
color: $accent-dark; color: $ok;
border-top: 3px solid $accent !important; border-top: 3px solid $ok !important;
} }
.thSupplierSel { .thSupplierSel {
background: rgba($gold-500, 0.02) !important; background: rgba($ok, 0.05) !important;
color: $text; color: $text;
border-top: 5px solid $accent !important; border-top: 5px solid $ok !important;
} }
.supplierHeaderCell { .supplierHeaderCell {
@@ -162,7 +162,7 @@
.recBadge { .recBadge {
font-size: 10px; font-size: 10px;
font-weight: 600; font-weight: 600;
background: $accent; background: $ok;
color: $surface; color: $surface;
border-radius: 10px; border-radius: 10px;
padding: 1px 6px; padding: 1px 6px;
@@ -205,7 +205,7 @@
font-size: 11px; font-size: 11px;
padding: 2px 10px; padding: 2px 10px;
border-radius: 3px; border-radius: 3px;
background: $accent; background: $ok;
color: $surface; color: $surface;
font-weight: 500; font-weight: 500;
white-space: nowrap; white-space: nowrap;
@@ -214,7 +214,7 @@
.selBadge { .selBadge {
font-size: 10px; font-size: 10px;
font-weight: 600; font-weight: 600;
background: $accent; background: $ok;
color: $surface; color: $surface;
border-radius: 10px; border-radius: 10px;
padding: 1px 6px; padding: 1px 6px;
@@ -198,6 +198,14 @@
overflow-y: auto; overflow-y: auto;
} }
// Модификатор для списка внутри диалога (замена согласующего): absolute-подсказки
// обрезались телом диалога (overflow-y: auto). В потоке список раздвигает диалог,
// а при длинном списке скроллится внутри него.
.suggestionsInline {
position: static;
box-shadow: none;
}
.suggestionItem { .suggestionItem {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
@@ -301,7 +301,7 @@ export const Step4Approval: React.FC<Props> = (props) => {
/> />
</FormField> </FormField>
{a.replaceDialog.suggestions.length > 0 && !a.replaceDialog.selected && ( {a.replaceDialog.suggestions.length > 0 && !a.replaceDialog.selected && (
<ul className={styles.suggestions}> <ul className={`${styles.suggestions} ${styles.suggestionsInline}`}>
{a.replaceDialog.suggestions.map((s) => ( {a.replaceDialog.suggestions.map((s) => (
<li <li
key={s.spId} key={s.spId}
@@ -248,26 +248,33 @@ export function useStep4Approval(args: UseStep4ApprovalArgs) {
setChain(updatedChain); setChain(updatedChain);
onSave({ approvalChain: updatedChain }); onSave({ approvalChain: updatedChain });
const nextPending = updatedChain.find((m) => m.status === "pending");
if (nextPending) {
if (currentMember.spApprovalId) {
await notify(currentMember.spApprovalId);
}
if (nextPending.spApprovalId) {
await notify(nextPending.spApprovalId);
}
}
const allDone = updatedChain.every( const allDone = updatedChain.every(
(m) => (m) =>
m.status === "approved" || m.status === "approved" ||
m.status === "skipped" || m.status === "skipped" ||
m.status === "recommends" m.status === "recommends"
); );
if (allDone) { if (allDone) {
// Финал: сначала статус «Согласовано», потом оповещение — иначе поток прочитает
// «На согласовании» и не отправит «Согласована» (а раньше на финале вообще ничего
// не слал, т.к. nextPending уже нет). Порядок как в ветке отклонения.
await service.updateOIDStatus(oid!.id, "approved"); await service.updateOIDStatus(oid!.id, "approved");
onSave({ oid: { ...oid!, status: "approved" }, approvalChain: updatedChain }); onSave({ oid: { ...oid!, status: "approved" }, approvalChain: updatedChain });
if (currentMember.spApprovalId) {
await notify(currentMember.spApprovalId);
}
onStepComplete(4); onStepComplete(4);
} else {
const nextPending = updatedChain.find((m) => m.status === "pending");
if (nextPending) {
if (currentMember.spApprovalId) {
await notify(currentMember.spApprovalId);
}
if (nextPending.spApprovalId) {
await notify(nextPending.spApprovalId);
}
}
} }
} else { } else {
const othersToDelete = chain.filter( const othersToDelete = chain.filter(