Объединены файлы правил системы в единую базу знаний v3.0 с устранением противоречий и дублирования. Создан rules-unified.md на основе rules.md, rules1.md и rules2.md с добавлением всех уникальных разделов. Обновлена терминология системы с соответствием реальной схеме БД (ТОВАР→PRODUCT, РАСХОДНИКИ→CONSUMABLE). Архивированы старые файлы правил в папку archive. Обновлены ссылки в CLAUDE.md и development-checklist.md на новый единый источник истины.
🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@ -169,6 +169,29 @@ export function CreateConsumablesSupplyPage() {
|
||||
);
|
||||
if (!product || !selectedSupplier) return;
|
||||
|
||||
// ✅ ПРОВЕРКА ОСТАТКОВ согласно rules2.md раздел 9.4.5
|
||||
if (quantity > 0) {
|
||||
// Проверяем доступность на складе
|
||||
if (product.stock !== undefined && quantity > product.stock) {
|
||||
toast.error(
|
||||
`Недостаточно товара на складе. Доступно: ${product.stock} ${product.unit || 'шт'}`
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
// Логируем попытку добавления для аудита
|
||||
console.log('📊 Stock check:', {
|
||||
action: 'add_to_cart',
|
||||
productId: product.id,
|
||||
productName: product.name,
|
||||
requested: quantity,
|
||||
available: product.stock || 'unlimited',
|
||||
result: quantity <= (product.stock || Infinity) ? 'allowed' : 'blocked',
|
||||
userId: selectedSupplier.id,
|
||||
timestamp: new Date().toISOString()
|
||||
});
|
||||
}
|
||||
|
||||
setSelectedConsumables((prev) => {
|
||||
const existing = prev.find((p) => p.id === productId);
|
||||
|
||||
@ -233,6 +256,18 @@ export function CreateConsumablesSupplyPage() {
|
||||
return;
|
||||
}
|
||||
|
||||
// ✅ ФИНАЛЬНАЯ ПРОВЕРКА ОСТАТКОВ перед созданием заказа
|
||||
for (const consumable of selectedConsumables) {
|
||||
const product = supplierProducts.find(p => p.id === consumable.id);
|
||||
if (product?.stock !== undefined && consumable.selectedQuantity > product.stock) {
|
||||
toast.error(
|
||||
`Товар "${consumable.name}" недоступен в количестве ${consumable.selectedQuantity}. ` +
|
||||
`Доступно: ${product.stock} ${product.unit || 'шт'}`
|
||||
);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Для селлеров требуется выбор фулфилмент-центра
|
||||
if (!selectedFulfillmentCenter) {
|
||||
toast.error("Выберите фулфилмент-центр для доставки");
|
||||
@ -261,12 +296,20 @@ export function CreateConsumablesSupplyPage() {
|
||||
return;
|
||||
}
|
||||
|
||||
// Проверяем дату
|
||||
// ✅ ПРОВЕРКА ДАТЫ согласно rules2.md - запрет прошедших дат
|
||||
const deliveryDateObj = new Date(deliveryDate);
|
||||
const today = new Date();
|
||||
today.setHours(0, 0, 0, 0);
|
||||
|
||||
if (isNaN(deliveryDateObj.getTime())) {
|
||||
toast.error("Некорректная дата поставки");
|
||||
return;
|
||||
}
|
||||
|
||||
if (deliveryDateObj < today) {
|
||||
toast.error("Нельзя выбрать прошедшую дату поставки");
|
||||
return;
|
||||
}
|
||||
|
||||
setIsCreatingSupply(true);
|
||||
|
||||
@ -948,7 +991,17 @@ export function CreateConsumablesSupplyPage() {
|
||||
<Input
|
||||
type="date"
|
||||
value={deliveryDate}
|
||||
onChange={(e) => setDeliveryDate(e.target.value)}
|
||||
onChange={(e) => {
|
||||
const selectedDate = new Date(e.target.value);
|
||||
const today = new Date();
|
||||
today.setHours(0,0,0,0);
|
||||
|
||||
if (selectedDate < today) {
|
||||
toast.error("Нельзя выбрать прошедшую дату поставки");
|
||||
return;
|
||||
}
|
||||
setDeliveryDate(e.target.value);
|
||||
}}
|
||||
className="bg-white/10 border-white/20 text-white h-8 text-sm"
|
||||
min={new Date().toISOString().split("T")[0]}
|
||||
required
|
||||
|
Reference in New Issue
Block a user