Создан единый источник истины rules-complete.md v9.1 с полной интеграцией всех правил системы. Консолидированы правила создания предметов по ролям, уточнен статус брака (НЕ РЕАЛИЗОВАНО), обновлен механизм учета ПЛАН/ФАКТ с заменой брака на потери при пересчете. Добавлен экономический учет расходников фулфилмента для селлера через рецептуру. Удалены дублирующие файлы правил (CLAUDE.md, development-checklist.md, work-protocols.md, violation-prevention-protocol.md, self-validation.md, description.md). Интегрированы UI структуры создания поставок и концепция многоуровневых таблиц.
🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@ -26,7 +26,7 @@ import {
|
||||
} from "lucide-react";
|
||||
import {
|
||||
GET_MY_COUNTERPARTIES,
|
||||
GET_ALL_PRODUCTS,
|
||||
GET_ORGANIZATION_PRODUCTS,
|
||||
GET_SUPPLY_ORDERS,
|
||||
GET_MY_SUPPLIES,
|
||||
GET_MY_FULFILLMENT_SUPPLIES,
|
||||
@ -112,19 +112,26 @@ export function CreateFulfillmentConsumablesSupplyPage() {
|
||||
productSearchQuery,
|
||||
});
|
||||
|
||||
// Загружаем товары для выбранного поставщика
|
||||
// Загружаем товары для выбранного поставщика с фильтрацией по типу CONSUMABLE
|
||||
const {
|
||||
data: productsData,
|
||||
loading: productsLoading,
|
||||
error: productsError,
|
||||
} = useQuery(GET_ALL_PRODUCTS, {
|
||||
} = useQuery(GET_ORGANIZATION_PRODUCTS, {
|
||||
skip: !selectedSupplier,
|
||||
variables: { search: productSearchQuery || null, category: null },
|
||||
variables: {
|
||||
organizationId: selectedSupplier.id,
|
||||
search: productSearchQuery || null,
|
||||
category: null,
|
||||
type: "CONSUMABLE" // Фильтруем только расходники согласно rules2.md
|
||||
},
|
||||
onCompleted: (data) => {
|
||||
console.log("✅ GET_ALL_PRODUCTS COMPLETED:", {
|
||||
totalProducts: data?.allProducts?.length || 0,
|
||||
console.log("✅ GET_ORGANIZATION_PRODUCTS COMPLETED:", {
|
||||
totalProducts: data?.organizationProducts?.length || 0,
|
||||
organizationId: selectedSupplier.id,
|
||||
type: "CONSUMABLE",
|
||||
products:
|
||||
data?.allProducts?.map((p) => ({
|
||||
data?.organizationProducts?.map((p) => ({
|
||||
id: p.id,
|
||||
name: p.name,
|
||||
type: p.type,
|
||||
@ -134,7 +141,7 @@ export function CreateFulfillmentConsumablesSupplyPage() {
|
||||
});
|
||||
},
|
||||
onError: (error) => {
|
||||
console.error("❌ GET_ALL_PRODUCTS ERROR:", error);
|
||||
console.error("❌ GET_ORGANIZATION_PRODUCTS ERROR:", error);
|
||||
},
|
||||
});
|
||||
|
||||
@ -160,14 +167,8 @@ export function CreateFulfillmentConsumablesSupplyPage() {
|
||||
);
|
||||
|
||||
// Фильтруем товары по выбранному поставщику
|
||||
// 📦 ТОЛЬКО РАСХОДНИКИ согласно правилам (раздел 2.1)
|
||||
const supplierProducts = selectedSupplier
|
||||
? (productsData?.allProducts || []).filter(
|
||||
(product: FulfillmentConsumableProduct) =>
|
||||
product.organization.id === selectedSupplier.id &&
|
||||
product.type === "CONSUMABLE" // Только расходники для фулфилмента
|
||||
)
|
||||
: [];
|
||||
// 📦 Получаем товары поставщика (уже отфильтрованы в GraphQL запросе по типу CONSUMABLE)
|
||||
const supplierProducts = productsData?.organizationProducts || [];
|
||||
|
||||
// Отладочное логирование
|
||||
React.useEffect(() => {
|
||||
@ -181,10 +182,10 @@ export function CreateFulfillmentConsumablesSupplyPage() {
|
||||
: null,
|
||||
productsLoading,
|
||||
productsError: productsError?.message,
|
||||
allProductsCount: productsData?.allProducts?.length || 0,
|
||||
organizationProductsCount: productsData?.organizationProducts?.length || 0,
|
||||
supplierProductsCount: supplierProducts.length,
|
||||
allProducts:
|
||||
productsData?.allProducts?.map((p) => ({
|
||||
organizationProducts:
|
||||
productsData?.organizationProducts?.map((p) => ({
|
||||
id: p.id,
|
||||
name: p.name,
|
||||
organizationId: p.organization.id,
|
||||
|
@ -25,7 +25,7 @@ import {
|
||||
} from "lucide-react";
|
||||
import {
|
||||
GET_MY_COUNTERPARTIES,
|
||||
GET_ALL_PRODUCTS,
|
||||
GET_ORGANIZATION_PRODUCTS,
|
||||
GET_SUPPLY_ORDERS,
|
||||
GET_MY_SUPPLIES,
|
||||
} from "@/graphql/queries";
|
||||
@ -91,12 +91,17 @@ export function MaterialsOrderForm() {
|
||||
GET_MY_COUNTERPARTIES
|
||||
);
|
||||
|
||||
// Загружаем товары для выбранного партнера
|
||||
// Загружаем товары для выбранного партнера с фильтрацией по типу CONSUMABLE
|
||||
const { data: productsData, loading: productsLoading } = useQuery(
|
||||
GET_ALL_PRODUCTS,
|
||||
GET_ORGANIZATION_PRODUCTS,
|
||||
{
|
||||
skip: !selectedPartner,
|
||||
variables: { search: null, category: null },
|
||||
variables: {
|
||||
organizationId: selectedPartner.id,
|
||||
search: null,
|
||||
category: null,
|
||||
type: "CONSUMABLE" // Фильтруем только расходники согласно rules2.md
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
@ -117,12 +122,8 @@ export function MaterialsOrderForm() {
|
||||
partner.inn?.toLowerCase().includes(searchQuery.toLowerCase())
|
||||
);
|
||||
|
||||
// Фильтруем товары по выбранному партнеру
|
||||
const partnerProducts = selectedPartner
|
||||
? (productsData?.allProducts || []).filter(
|
||||
(product: Product) => product.organization.id === selectedPartner.id
|
||||
)
|
||||
: [];
|
||||
// Получаем товары партнера (уже отфильтрованы в GraphQL запросе)
|
||||
const partnerProducts = productsData?.organizationProducts || [];
|
||||
|
||||
const formatCurrency = (amount: number) => {
|
||||
return new Intl.NumberFormat("ru-RU", {
|
||||
|
Reference in New Issue
Block a user