Add material transformation planning

This commit is contained in:
Cauê Faleiros
2026-08-27 10:44:49 -03:00
parent da6f3b2955
commit 442b23dc62
6 changed files with 325 additions and 3 deletions

View File

@@ -1,4 +1,4 @@
import type { AuthUser, CampaignPreview, CampaignProcessSummary, CampaignQueueSummary, CatalogCategory, CatalogCategoryPayload, CatalogProduct, CatalogProductPayload, CatalogSummary, ClientAnalyticsItem, ClientDetailsAnalytics, ClientFilterOptions, ClientMetadataFilters, ClientPurchasePatternAnalytics, ConsumptionReference, ConsumptionReferencePayload, CreateProductionOrdersResult, CreateUserResult, CutPlanLotReservationPayload, CuttingSettings, DashboardAnalytics, DateRange, GraphsStockBalanceHistoryItem, GraphsStockBalancePayload, ManagedUser, OperationalUser, OrderData, OlistRunDetails, OlistStatus, ProductAnalyticsItem, ProductComposition, ProductCompositionImportSummary, ProductCompositionPayload, ProductDetailsAnalytics, ProductionOrderDefectPayload, ProductionOrderExecutionPayload, ProductionOrderImportData, ProductionOrderItem, ProductionOrderPayload, ProductionOrderStatus, ProductionOrderSummary, ProductionPlan, ProductionPlanPayload, ProductionWorkstation, ProductionWorkstationPayload, RfmAnalytics, SellerAnalyticsItem, SellerDetailsAnalytics, StockData, SupplyFabricPlan, SupplyFabricPlanPayload, SupplyInventoryAdjustmentPayload, SupplyLot, SupplyMaterialDetailsPayload, SupplyProductionExitPayload, SupplyPurchaseNeed, SupplyPurchaseOrder, SupplyPurchaseOrderPayload, SupplyPurchaseOrderStatus, SupplyReceipt, SupplyReceiptPayload, SupplySummary } from './types';
import type { AuthUser, CampaignPreview, CampaignProcessSummary, CampaignQueueSummary, CatalogCategory, CatalogCategoryPayload, CatalogProduct, CatalogProductPayload, CatalogSummary, ClientAnalyticsItem, ClientDetailsAnalytics, ClientFilterOptions, ClientMetadataFilters, ClientPurchasePatternAnalytics, ConsumptionReference, ConsumptionReferencePayload, CreateProductionOrdersResult, CreateUserResult, CutPlanLotReservationPayload, CuttingSettings, DashboardAnalytics, DateRange, GraphsStockBalanceHistoryItem, GraphsStockBalancePayload, ManagedUser, MaterialTransformationStatus, OperationalUser, OrderData, OlistRunDetails, OlistStatus, ProductAnalyticsItem, ProductComposition, ProductCompositionImportSummary, ProductCompositionPayload, ProductDetailsAnalytics, ProductionOrderDefectPayload, ProductionOrderExecutionPayload, ProductionOrderImportData, ProductionOrderItem, ProductionOrderPayload, ProductionOrderStatus, ProductionOrderSummary, ProductionPlan, ProductionPlanPayload, ProductionWorkstation, ProductionWorkstationPayload, RfmAnalytics, SellerAnalyticsItem, SellerDetailsAnalytics, StockData, SupplyFabricPlan, SupplyFabricPlanPayload, SupplyInventoryAdjustmentPayload, SupplyLot, SupplyMaterialDetailsPayload, SupplyMaterialTransformation, SupplyMaterialTransformationPayload, SupplyProductionExitPayload, SupplyPurchaseNeed, SupplyPurchaseOrder, SupplyPurchaseOrderPayload, SupplyPurchaseOrderStatus, SupplyReceipt, SupplyReceiptPayload, SupplySummary } from './types';
import { formatDateParam } from './dateRanges';
const API_URL = import.meta.env.VITE_API_URL || '/api';
@@ -732,6 +732,35 @@ export const deleteSupplyFabricPlan = async (id: number): Promise<void> => {
}
};
export const fetchSupplyMaterialTransformations = async (): Promise<SupplyMaterialTransformation[]> => {
try {
const response = await authFetch('/supply/material-transformations');
if (!response.ok) return [];
return await response.json();
} catch (error) {
console.error('Fetch material transformations failed', error);
return [];
}
};
export const createSupplyMaterialTransformation = async (payload: SupplyMaterialTransformationPayload): Promise<SupplyMaterialTransformation> => {
const response = await authFetch('/supply/material-transformations', {
method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(payload)
});
const data = await response.json().catch(() => null);
if (!response.ok) throw new Error(data?.error || 'Não foi possível salvar a transformação.');
return data as SupplyMaterialTransformation;
};
export const updateSupplyMaterialTransformationStatus = async (id: number, status: MaterialTransformationStatus): Promise<SupplyMaterialTransformation> => {
const response = await authFetch(`/supply/material-transformations/${id}/status`, {
method: 'PATCH', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ status })
});
const data = await response.json().catch(() => null);
if (!response.ok) throw new Error(data?.error || 'Não foi possível atualizar a transformação.');
return data as SupplyMaterialTransformation;
};
export const fetchSupplyPurchaseNeeds = async (): Promise<SupplyPurchaseNeed[]> => {
try {
const response = await authFetch('/supply/purchase-needs');

File diff suppressed because one or more lines are too long

View File

@@ -535,6 +535,27 @@ export interface SupplyFabricPlan {
updatedAt: string;
}
export type MaterialTransformationStage = 'knitting' | 'dyeing' | 'finishing';
export type MaterialTransformationStatus = 'planned' | 'in_progress' | 'completed' | 'canceled';
export interface SupplyMaterialTransformation {
id: number;
batchCode: string;
stage: MaterialTransformationStage;
inputMaterial: string;
inputQuantityKg: number;
outputMaterial: string;
outputColor: string;
expectedLossPercent: number;
expectedOutputKg: number;
supplier: string;
priority: string;
status: MaterialTransformationStatus;
notes: string;
createdAt: string;
updatedAt: string;
}
export type SupplyPurchaseOrderStatus = 'draft' | 'sent' | 'approved' | 'received' | 'canceled';
export interface SupplyPurchaseOrderItem {
@@ -635,6 +656,19 @@ export type SupplyFabricPlanPayload = {
priority?: string;
};
export type SupplyMaterialTransformationPayload = {
batchCode?: string;
stage: MaterialTransformationStage;
inputMaterial: string;
inputQuantityKg: number | string;
outputMaterial: string;
outputColor?: string;
expectedLossPercent?: number | string;
supplier?: string;
priority?: string;
notes?: string;
};
export type SupplyInventoryAdjustmentPayload = {
countedQuantity: number | string;
reason: string;