All checks were successful
Deploy MES Core / deploy (push) Successful in 13s
649 lines
32 KiB
HTML
649 lines
32 KiB
HTML
{% extends 'base.html' %}
|
||
|
||
{% block content %}
|
||
<div class="row justify-content-center">
|
||
<div class="col-lg-10 col-xl-8">
|
||
<div class="card shadow border-secondary">
|
||
<div class="card-header border-secondary py-3 d-flex justify-content-between align-items-center">
|
||
<h3 class="text-accent mb-0"><i class="bi bi-plus-circle me-2"></i>Новое задание</h3>
|
||
{% if request.GET.next %}
|
||
<a class="btn btn-outline-secondary btn-sm" href="{{ request.GET.next }}">
|
||
<i class="bi bi-arrow-left me-1"></i>Назад
|
||
</a>
|
||
{% else %}
|
||
<a class="btn btn-outline-secondary btn-sm" href="{% url 'planning' %}">
|
||
<i class="bi bi-arrow-left me-1"></i>Назад
|
||
</a>
|
||
{% endif %}
|
||
</div>
|
||
|
||
<form method="post" enctype="multipart/form-data" class="card-body p-4">
|
||
{% csrf_token %}
|
||
<input type="hidden" name="next" value="{{ request.GET.next }}">
|
||
|
||
{% if form.non_field_errors %}
|
||
<div class="alert alert-danger">
|
||
{% for e in form.non_field_errors %}<div>{{ e }}</div>{% endfor %}
|
||
</div>
|
||
{% endif %}
|
||
|
||
<div class="row g-3">
|
||
<div class="col-12">
|
||
<div class="card border-secondary">
|
||
<div class="card-header border-secondary py-2">
|
||
<strong>Деталь</strong>
|
||
</div>
|
||
<div class="card-body">
|
||
<div class="row g-3">
|
||
<div class="col-12">
|
||
<label class="form-label small text-muted">{{ form.drawing_name.label }}</label>
|
||
{{ form.drawing_name }}
|
||
{% for e in form.drawing_name.errors %}<div class="text-danger small">{{ e }}</div>{% endfor %}
|
||
</div>
|
||
<div class="col-md-4">
|
||
<label class="form-label small text-muted">{{ form.quantity_ordered.label }}</label>
|
||
{{ form.quantity_ordered }}
|
||
{% for e in form.quantity_ordered.errors %}<div class="text-danger small">{{ e }}</div>{% endfor %}
|
||
</div>
|
||
<div class="col-md-4">
|
||
<label class="form-label small text-muted">{{ form.size_value.label }}</label>
|
||
{{ form.size_value }}
|
||
{% for e in form.size_value.errors %}<div class="text-danger small">{{ e }}</div>{% endfor %}
|
||
</div>
|
||
<div class="col-md-4 d-flex align-items-end">
|
||
<div class="form-check form-switch">
|
||
{{ form.is_bend }}
|
||
<label class="form-check-label ms-2">{{ form.is_bend.label }}</label>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="col-12">
|
||
<div class="card border-secondary">
|
||
<div class="card-header border-secondary py-2">
|
||
<strong>Файлы</strong>
|
||
</div>
|
||
<div class="card-body">
|
||
<div class="row g-3">
|
||
<div class="col-md-6">
|
||
<label class="form-label small text-muted">{{ form.drawing_file.label }}</label>
|
||
{{ form.drawing_file }}
|
||
<button type="button" id="fillNameFromSource" class="btn btn-outline-secondary btn-sm mt-2" disabled>
|
||
в название (из исходника)
|
||
</button>
|
||
</div>
|
||
<div class="col-md-6">
|
||
<label class="form-label small text-muted">{{ form.extra_drawing.label }}</label>
|
||
{{ form.extra_drawing }}
|
||
<button type="button" id="fillNameFromPdf" class="btn btn-outline-secondary btn-sm mt-2" disabled>
|
||
в название (из чертежа)
|
||
</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="col-12">
|
||
<div class="card border-secondary">
|
||
<div class="card-header border-secondary py-2">
|
||
<strong>Сделка и материал</strong>
|
||
</div>
|
||
<div class="card-body">
|
||
<div class="row g-3">
|
||
<div class="col-md-6">
|
||
<label class="form-label small text-muted">{{ form.deal.label }}</label>
|
||
<div class="d-flex gap-2">
|
||
<div class="flex-grow-1">{{ form.deal }}</div>
|
||
<button type="button" class="btn btn-outline-accent btn-sm" data-bs-toggle="modal" data-bs-target="#dealModal" data-mode="create">Создать</button>
|
||
<button type="button" class="btn btn-outline-secondary btn-sm" id="dealEditBtn" data-bs-toggle="modal" data-bs-target="#dealModal" data-mode="edit" disabled>Редакт.</button>
|
||
</div>
|
||
{% for e in form.deal.errors %}<div class="text-danger small">{{ e }}</div>{% endfor %}
|
||
</div>
|
||
|
||
<div class="col-md-6">
|
||
<label class="form-label small text-muted">{{ form.material.label }}</label>
|
||
<div class="d-flex gap-2">
|
||
<div class="flex-grow-1">{{ form.material }}</div>
|
||
<button type="button" class="btn btn-outline-accent btn-sm" data-bs-toggle="modal" data-bs-target="#materialModal" data-mode="create">Создать</button>
|
||
<button type="button" class="btn btn-outline-secondary btn-sm" id="materialEditBtn" data-bs-toggle="modal" data-bs-target="#materialModal" data-mode="edit" disabled>Редакт.</button>
|
||
</div>
|
||
{% for e in form.material.errors %}<div class="text-danger small">{{ e }}</div>{% endfor %}
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="d-flex justify-content-end mt-4">
|
||
<button type="submit" class="btn btn-outline-accent px-4 fw-bold">
|
||
<i class="bi bi-save me-2"></i>Создать
|
||
</button>
|
||
</div>
|
||
</form>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="modal fade" id="dealModal" tabindex="-1" aria-hidden="true">
|
||
<div class="modal-dialog">
|
||
<div class="modal-content border-secondary">
|
||
<div class="modal-header border-secondary">
|
||
<h5 class="modal-title">Сделка</h5>
|
||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Закрыть"></button>
|
||
</div>
|
||
<div class="modal-body">
|
||
<input type="hidden" id="dealId">
|
||
<div class="mb-3">
|
||
<label class="form-label small text-muted">№ Сделки</label>
|
||
<input type="text" class="form-control border-secondary" id="dealNumber">
|
||
</div>
|
||
<div class="mb-3">
|
||
<label class="form-label small text-muted">Статус</label>
|
||
<select class="form-select border-secondary" id="dealStatus">
|
||
<option value="lead">Зашла</option>
|
||
<option value="work" selected>В работе</option>
|
||
<option value="done">Завершена</option>
|
||
</select>
|
||
</div>
|
||
<div class="mb-3">
|
||
<label class="form-label small text-muted">Компания</label>
|
||
<div class="d-flex gap-2">
|
||
<select class="form-select border-secondary" id="dealCompany">
|
||
<option value="">— не выбрано —</option>
|
||
{% for c in companies %}
|
||
<option value="{{ c.id }}">{{ c.name }}</option>
|
||
{% endfor %}
|
||
</select>
|
||
<button type="button" class="btn btn-outline-accent btn-sm" id="openCompanyModalBtn">
|
||
Создать
|
||
</button>
|
||
</div>
|
||
</div>
|
||
<div class="mb-0">
|
||
<label class="form-label small text-muted">Описание</label>
|
||
<textarea class="form-control border-secondary" rows="3" id="dealDescription"></textarea>
|
||
</div>
|
||
</div>
|
||
<div class="modal-footer border-secondary">
|
||
<button type="button" class="btn btn-outline-secondary" data-bs-dismiss="modal">Отмена</button>
|
||
<button type="button" class="btn btn-outline-accent" id="dealSaveBtn">Сохранить</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="modal fade" id="materialModal" tabindex="-1" aria-hidden="true">
|
||
<div class="modal-dialog">
|
||
<div class="modal-content border-secondary">
|
||
<div class="modal-header border-secondary">
|
||
<h5 class="modal-title">Материал</h5>
|
||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Закрыть"></button>
|
||
</div>
|
||
<div class="modal-body">
|
||
<input type="hidden" id="materialId">
|
||
<div class="row g-3">
|
||
<div class="col-md-6">
|
||
<label class="form-label small text-muted">Категория</label>
|
||
<div class="d-flex gap-2">
|
||
<select class="form-select border-secondary" id="materialCategory">
|
||
<option value="">— выбрать —</option>
|
||
{% for c in material_categories %}
|
||
<option value="{{ c.id }}">{{ c.name }}</option>
|
||
{% endfor %}
|
||
</select>
|
||
<button type="button" class="btn btn-outline-accent btn-sm" id="openCategoryModalBtn">
|
||
Создать
|
||
</button>
|
||
</div>
|
||
</div>
|
||
<div class="col-md-6">
|
||
<label class="form-label small text-muted">Марка стали</label>
|
||
<div class="d-flex gap-2">
|
||
<select class="form-select border-secondary" id="materialGrade">
|
||
<option value="">— не выбрано —</option>
|
||
{% for g in steel_grades %}
|
||
<option value="{{ g.id }}">{{ g.name }}</option>
|
||
{% endfor %}
|
||
</select>
|
||
<button type="button" class="btn btn-outline-accent btn-sm" id="openGradeModalBtn">
|
||
Создать
|
||
</button>
|
||
</div>
|
||
</div>
|
||
<div class="col-12">
|
||
<label class="form-label small text-muted">Наименование (размер/характеристики)</label>
|
||
<input type="text" class="form-control border-secondary" id="materialName">
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="modal-footer border-secondary">
|
||
<button type="button" class="btn btn-outline-secondary" data-bs-dismiss="modal">Отмена</button>
|
||
<button type="button" class="btn btn-outline-accent" id="materialSaveBtn">Сохранить</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="modal fade" id="companyModal" tabindex="-1" aria-hidden="true">
|
||
<div class="modal-dialog">
|
||
<div class="modal-content border-secondary">
|
||
<div class="modal-header border-secondary">
|
||
<h5 class="modal-title">Компания</h5>
|
||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Закрыть"></button>
|
||
</div>
|
||
<div class="modal-body">
|
||
<input type="hidden" id="companyId">
|
||
<div class="mb-3">
|
||
<label class="form-label small text-muted">Название</label>
|
||
<input type="text" class="form-control border-secondary" id="companyName">
|
||
</div>
|
||
<div class="mb-0">
|
||
<label class="form-label small text-muted">Примечание</label>
|
||
<textarea class="form-control border-secondary" rows="3" id="companyDescription"></textarea>
|
||
</div>
|
||
</div>
|
||
<div class="modal-footer border-secondary">
|
||
<button type="button" class="btn btn-outline-secondary" data-bs-dismiss="modal">Отмена</button>
|
||
<button type="button" class="btn btn-outline-accent" id="companySaveBtn">Сохранить</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="modal fade" id="categoryModal" tabindex="-1" aria-hidden="true">
|
||
<div class="modal-dialog">
|
||
<div class="modal-content border-secondary">
|
||
<div class="modal-header border-secondary">
|
||
<h5 class="modal-title">Категория материала</h5>
|
||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Закрыть"></button>
|
||
</div>
|
||
<div class="modal-body">
|
||
<input type="hidden" id="categoryId">
|
||
<div class="mb-3">
|
||
<label class="form-label small text-muted">Название</label>
|
||
<input type="text" class="form-control border-secondary" id="categoryName">
|
||
</div>
|
||
<div class="mb-0">
|
||
<label class="form-label small text-muted">ГОСТ</label>
|
||
<input type="text" class="form-control border-secondary" id="categoryGost">
|
||
</div>
|
||
</div>
|
||
<div class="modal-footer border-secondary">
|
||
<button type="button" class="btn btn-outline-secondary" data-bs-dismiss="modal">Отмена</button>
|
||
<button type="button" class="btn btn-outline-accent" id="categorySaveBtn">Сохранить</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="modal fade" id="gradeModal" tabindex="-1" aria-hidden="true">
|
||
<div class="modal-dialog">
|
||
<div class="modal-content border-secondary">
|
||
<div class="modal-header border-secondary">
|
||
<h5 class="modal-title">Марка стали</h5>
|
||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Закрыть"></button>
|
||
</div>
|
||
<div class="modal-body">
|
||
<input type="hidden" id="gradeId">
|
||
<div class="mb-3">
|
||
<label class="form-label small text-muted">Марка стали</label>
|
||
<input type="text" class="form-control border-secondary" id="gradeName">
|
||
</div>
|
||
<div class="mb-0">
|
||
<label class="form-label small text-muted">ГОСТ/ТУ</label>
|
||
<input type="text" class="form-control border-secondary" id="gradeGost">
|
||
</div>
|
||
</div>
|
||
<div class="modal-footer border-secondary">
|
||
<button type="button" class="btn btn-outline-secondary" data-bs-dismiss="modal">Отмена</button>
|
||
<button type="button" class="btn btn-outline-accent" id="gradeSaveBtn">Сохранить</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<script>
|
||
document.addEventListener('DOMContentLoaded', function () {
|
||
const drawingFile = document.getElementById('id_drawing_file');
|
||
const extraDrawing = document.getElementById('id_extra_drawing');
|
||
const drawingName = document.getElementById('id_drawing_name');
|
||
const qtyOrdered = document.getElementById('id_quantity_ordered');
|
||
const sizeValue = document.getElementById('id_size_value');
|
||
|
||
const fillFromSource = document.getElementById('fillNameFromSource');
|
||
const fillFromPdf = document.getElementById('fillNameFromPdf');
|
||
|
||
const dealSelect = document.getElementById('id_deal');
|
||
const materialSelect = document.getElementById('id_material');
|
||
const dealEditBtn = document.getElementById('dealEditBtn');
|
||
const materialEditBtn = document.getElementById('materialEditBtn');
|
||
|
||
const dealModal = document.getElementById('dealModal');
|
||
const dealId = document.getElementById('dealId');
|
||
const dealNumber = document.getElementById('dealNumber');
|
||
const dealCompany = document.getElementById('dealCompany');
|
||
const dealDescription = document.getElementById('dealDescription');
|
||
const dealStatus = document.getElementById('dealStatus');
|
||
const dealSaveBtn = document.getElementById('dealSaveBtn');
|
||
|
||
const companyModal = document.getElementById('companyModal');
|
||
const companyId = document.getElementById('companyId');
|
||
const companyName = document.getElementById('companyName');
|
||
const companyDescription = document.getElementById('companyDescription');
|
||
const companySaveBtn = document.getElementById('companySaveBtn');
|
||
const openCompanyModalBtn = document.getElementById('openCompanyModalBtn');
|
||
|
||
const materialModal = document.getElementById('materialModal');
|
||
const materialId = document.getElementById('materialId');
|
||
const materialCategory = document.getElementById('materialCategory');
|
||
const materialGrade = document.getElementById('materialGrade');
|
||
const materialName = document.getElementById('materialName');
|
||
const materialSaveBtn = document.getElementById('materialSaveBtn');
|
||
|
||
const categoryModal = document.getElementById('categoryModal');
|
||
const categoryId = document.getElementById('categoryId');
|
||
const categoryName = document.getElementById('categoryName');
|
||
const categoryGost = document.getElementById('categoryGost');
|
||
const categorySaveBtn = document.getElementById('categorySaveBtn');
|
||
const openCategoryModalBtn = document.getElementById('openCategoryModalBtn');
|
||
|
||
const gradeModal = document.getElementById('gradeModal');
|
||
const gradeId = document.getElementById('gradeId');
|
||
const gradeName = document.getElementById('gradeName');
|
||
const gradeGost = document.getElementById('gradeGost');
|
||
const gradeSaveBtn = document.getElementById('gradeSaveBtn');
|
||
const openGradeModalBtn = document.getElementById('openGradeModalBtn');
|
||
|
||
function getCookie(name) {
|
||
const value = `; ${document.cookie}`;
|
||
const parts = value.split(`; ${name}=`);
|
||
if (parts.length === 2) return parts.pop().split(';').shift();
|
||
return '';
|
||
}
|
||
|
||
function filenameBase(path) {
|
||
if (!path) return '';
|
||
const justName = path.split('\\').pop().split('/').pop();
|
||
const idx = justName.lastIndexOf('.');
|
||
return idx > 0 ? justName.slice(0, idx) : justName;
|
||
}
|
||
|
||
function updateFileButtons() {
|
||
const hasSource = drawingFile && drawingFile.files && drawingFile.files.length > 0;
|
||
const hasPdf = extraDrawing && extraDrawing.files && extraDrawing.files.length > 0;
|
||
if (fillFromSource) fillFromSource.disabled = !hasSource;
|
||
if (fillFromPdf) fillFromPdf.disabled = !hasPdf;
|
||
}
|
||
|
||
function tryFillFromDxfFilename(filename) {
|
||
if (!filename) return false;
|
||
|
||
const isDxf = filename.toLowerCase().endsWith('.dxf');
|
||
if (!isDxf) return false;
|
||
|
||
// Поддерживаем паттерн в имени файла вида "-s2n45".
|
||
// На практике встречаются варианты: "s2n45", "-s2_n45", "_s2-n45" и т.п.
|
||
// Поэтому ищем "s<число> ... n<целое>" в любом месте имени, разрешая разделители между ними.
|
||
const base = filenameBase(filename);
|
||
const normalized = base.replace(/\s+/g, '');
|
||
const m = normalized.match(/s([0-9]+(?:[\.,][0-9]+)?)[^0-9a-zA-Z]*n([0-9]+)/);
|
||
if (!m) return false;
|
||
|
||
const s = (m[1] || '').replace(',', '.');
|
||
const n = (m[2] || '').trim();
|
||
|
||
// По твоей просьбе: перезатираем значения, даже если пользователь что-то уже вводил.
|
||
if (sizeValue) {
|
||
sizeValue.value = s;
|
||
sizeValue.dispatchEvent(new Event('input', { bubbles: true }));
|
||
}
|
||
if (qtyOrdered) {
|
||
qtyOrdered.value = n;
|
||
qtyOrdered.dispatchEvent(new Event('input', { bubbles: true }));
|
||
}
|
||
return true;
|
||
}
|
||
|
||
if (drawingFile) drawingFile.addEventListener('change', function () {
|
||
updateFileButtons();
|
||
if (!drawingFile.files || drawingFile.files.length === 0) return;
|
||
|
||
const fname = drawingFile.files[0].name;
|
||
|
||
// По твоей просьбе: при выборе исходника перезаполняем «Наименование» из имени файла.
|
||
if (drawingName) drawingName.value = filenameBase(fname);
|
||
|
||
// Пытаемся распарсить «Размер» и «Требуется» из имени DXF.
|
||
tryFillFromDxfFilename(fname);
|
||
});
|
||
if (extraDrawing) extraDrawing.addEventListener('change', updateFileButtons);
|
||
updateFileButtons();
|
||
|
||
if (fillFromSource) {
|
||
fillFromSource.addEventListener('click', function () {
|
||
if (!drawingFile || !drawingFile.files || drawingFile.files.length === 0) return;
|
||
const fname = drawingFile.files[0].name;
|
||
const base = filenameBase(fname);
|
||
|
||
// Кнопка также перезаполняет значения из имени исходника.
|
||
if (drawingName) drawingName.value = base;
|
||
tryFillFromDxfFilename(fname);
|
||
});
|
||
}
|
||
|
||
if (fillFromPdf) {
|
||
fillFromPdf.addEventListener('click', function () {
|
||
if (!extraDrawing || !extraDrawing.files || extraDrawing.files.length === 0) return;
|
||
const base = filenameBase(extraDrawing.files[0].name);
|
||
if (drawingName) drawingName.value = base;
|
||
});
|
||
}
|
||
|
||
function updateEditButtons() {
|
||
if (dealEditBtn) dealEditBtn.disabled = !(dealSelect && dealSelect.value);
|
||
if (materialEditBtn) materialEditBtn.disabled = !(materialSelect && materialSelect.value);
|
||
}
|
||
|
||
function openChildModal(parentEl, childEl) {
|
||
if (!parentEl || !childEl) return;
|
||
childEl.dataset.returnTo = parentEl.id;
|
||
const parent = bootstrap.Modal.getOrCreateInstance(parentEl);
|
||
const child = bootstrap.Modal.getOrCreateInstance(childEl);
|
||
parentEl.addEventListener('hidden.bs.modal', function () {
|
||
child.show();
|
||
}, { once: true });
|
||
parent.hide();
|
||
}
|
||
|
||
function returnToParent(childEl) {
|
||
const returnId = childEl ? childEl.dataset.returnTo : '';
|
||
if (!returnId) return;
|
||
delete childEl.dataset.returnTo;
|
||
const parentEl = document.getElementById(returnId);
|
||
if (parentEl) bootstrap.Modal.getOrCreateInstance(parentEl).show();
|
||
}
|
||
|
||
if (companyModal) companyModal.addEventListener('hidden.bs.modal', function () { returnToParent(companyModal); });
|
||
if (categoryModal) categoryModal.addEventListener('hidden.bs.modal', function () { returnToParent(categoryModal); });
|
||
if (gradeModal) gradeModal.addEventListener('hidden.bs.modal', function () { returnToParent(gradeModal); });
|
||
|
||
if (openCompanyModalBtn) openCompanyModalBtn.addEventListener('click', function () { openChildModal(dealModal, companyModal); });
|
||
if (openCategoryModalBtn) openCategoryModalBtn.addEventListener('click', function () { openChildModal(materialModal, categoryModal); });
|
||
if (openGradeModalBtn) openGradeModalBtn.addEventListener('click', function () { openChildModal(materialModal, gradeModal); });
|
||
|
||
if (dealSelect) dealSelect.addEventListener('change', updateEditButtons);
|
||
if (materialSelect) materialSelect.addEventListener('change', updateEditButtons);
|
||
updateEditButtons();
|
||
|
||
async function postForm(url, data) {
|
||
const csrftoken = getCookie('csrftoken');
|
||
const res = await fetch(url, {
|
||
method: 'POST',
|
||
headers: {
|
||
'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8',
|
||
'X-CSRFToken': csrftoken,
|
||
},
|
||
body: new URLSearchParams(data).toString(),
|
||
});
|
||
if (!res.ok) throw new Error('request_failed');
|
||
return await res.json();
|
||
}
|
||
|
||
async function getJson(url) {
|
||
const res = await fetch(url, { method: 'GET' });
|
||
if (!res.ok) throw new Error('request_failed');
|
||
return await res.json();
|
||
}
|
||
|
||
function upsertSelectOption(select, id, label) {
|
||
if (!select) return;
|
||
let opt = select.querySelector(`option[value="${id}"]`);
|
||
if (!opt) {
|
||
opt = document.createElement('option');
|
||
opt.value = String(id);
|
||
select.appendChild(opt);
|
||
}
|
||
opt.textContent = label;
|
||
select.value = String(id);
|
||
select.dispatchEvent(new Event('change'));
|
||
}
|
||
|
||
if (dealModal) {
|
||
dealModal.addEventListener('show.bs.modal', async function (event) {
|
||
if (!event.relatedTarget) return;
|
||
const mode = event.relatedTarget.getAttribute('data-mode') || 'create';
|
||
dealId.value = '';
|
||
dealNumber.value = '';
|
||
dealCompany.value = '';
|
||
dealDescription.value = '';
|
||
if (dealStatus) dealStatus.value = 'work';
|
||
|
||
if (mode === 'edit' && dealSelect && dealSelect.value) {
|
||
const data = await getJson(`/planning/deal/${dealSelect.value}/json/`);
|
||
dealId.value = data.id;
|
||
dealNumber.value = data.number || '';
|
||
dealCompany.value = data.company_id ? String(data.company_id) : '';
|
||
dealDescription.value = data.description || '';
|
||
if (dealStatus) dealStatus.value = data.status || 'work';
|
||
}
|
||
});
|
||
}
|
||
|
||
if (dealSaveBtn) {
|
||
dealSaveBtn.addEventListener('click', async function () {
|
||
const payload = {
|
||
id: dealId.value,
|
||
number: dealNumber.value,
|
||
company_id: dealCompany.value,
|
||
status: dealStatus ? dealStatus.value : 'work',
|
||
description: dealDescription.value,
|
||
};
|
||
const data = await postForm('{% url "deal_upsert" %}', payload);
|
||
upsertSelectOption(dealSelect, data.id, data.label);
|
||
bootstrap.Modal.getInstance(dealModal).hide();
|
||
});
|
||
}
|
||
|
||
if (companyModal) {
|
||
companyModal.addEventListener('show.bs.modal', function () {
|
||
companyId.value = '';
|
||
companyName.value = '';
|
||
companyDescription.value = '';
|
||
});
|
||
}
|
||
|
||
if (companySaveBtn) {
|
||
companySaveBtn.addEventListener('click', async function () {
|
||
const payload = {
|
||
id: companyId.value,
|
||
name: companyName.value,
|
||
description: companyDescription.value,
|
||
};
|
||
const data = await postForm('{% url "company_upsert" %}', payload);
|
||
upsertSelectOption(dealCompany, data.id, data.label);
|
||
bootstrap.Modal.getInstance(companyModal).hide();
|
||
});
|
||
}
|
||
|
||
if (categoryModal) {
|
||
categoryModal.addEventListener('show.bs.modal', function () {
|
||
categoryId.value = '';
|
||
categoryName.value = '';
|
||
categoryGost.value = '';
|
||
});
|
||
}
|
||
|
||
if (categorySaveBtn) {
|
||
categorySaveBtn.addEventListener('click', async function () {
|
||
const payload = {
|
||
id: categoryId.value,
|
||
name: categoryName.value,
|
||
gost_standard: categoryGost.value,
|
||
};
|
||
const data = await postForm('{% url "material_category_upsert" %}', payload);
|
||
upsertSelectOption(materialCategory, data.id, data.label);
|
||
bootstrap.Modal.getInstance(categoryModal).hide();
|
||
});
|
||
}
|
||
|
||
if (gradeModal) {
|
||
gradeModal.addEventListener('show.bs.modal', function () {
|
||
gradeId.value = '';
|
||
gradeName.value = '';
|
||
gradeGost.value = '';
|
||
});
|
||
}
|
||
|
||
if (gradeSaveBtn) {
|
||
gradeSaveBtn.addEventListener('click', async function () {
|
||
const payload = {
|
||
id: gradeId.value,
|
||
name: gradeName.value,
|
||
gost_standard: gradeGost.value,
|
||
};
|
||
const data = await postForm('{% url "steel_grade_upsert" %}', payload);
|
||
upsertSelectOption(materialGrade, data.id, data.label);
|
||
bootstrap.Modal.getInstance(gradeModal).hide();
|
||
});
|
||
}
|
||
|
||
if (materialModal) {
|
||
materialModal.addEventListener('show.bs.modal', async function (event) {
|
||
if (!event.relatedTarget) return;
|
||
const mode = event.relatedTarget.getAttribute('data-mode') || 'create';
|
||
materialId.value = '';
|
||
materialCategory.value = '';
|
||
materialGrade.value = '';
|
||
materialName.value = '';
|
||
|
||
if (mode === 'edit' && materialSelect && materialSelect.value) {
|
||
const data = await getJson(`/planning/material/${materialSelect.value}/json/`);
|
||
materialId.value = data.id;
|
||
materialCategory.value = data.category_id ? String(data.category_id) : '';
|
||
materialGrade.value = data.steel_grade_id ? String(data.steel_grade_id) : '';
|
||
materialName.value = data.name || '';
|
||
}
|
||
});
|
||
}
|
||
|
||
if (materialSaveBtn) {
|
||
materialSaveBtn.addEventListener('click', async function () {
|
||
const payload = {
|
||
id: materialId.value,
|
||
category_id: materialCategory.value,
|
||
steel_grade_id: materialGrade.value,
|
||
name: materialName.value,
|
||
};
|
||
const data = await postForm('{% url "material_upsert" %}', payload);
|
||
upsertSelectOption(materialSelect, data.id, data.label);
|
||
bootstrap.Modal.getInstance(materialModal).hide();
|
||
});
|
||
}
|
||
});
|
||
</script>
|
||
{% endblock %} |