@fayz-ai/plugin-inventory 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/InventoryContext.d.ts +37 -0
- package/dist/InventoryContext.d.ts.map +1 -0
- package/dist/InventoryPage.d.ts +13 -0
- package/dist/InventoryPage.d.ts.map +1 -0
- package/dist/components/InventoryGeneralSettings.d.ts +3 -0
- package/dist/components/InventoryGeneralSettings.d.ts.map +1 -0
- package/dist/components/InventoryOnboarding.d.ts +5 -0
- package/dist/components/InventoryOnboarding.d.ts.map +1 -0
- package/dist/components/InventorySettings.d.ts +8 -0
- package/dist/components/InventorySettings.d.ts.map +1 -0
- package/dist/data/index.d.ts +3 -0
- package/dist/data/index.d.ts.map +1 -0
- package/dist/data/mock.d.ts +3 -0
- package/dist/data/mock.d.ts.map +1 -0
- package/dist/data/supabase.d.ts +3 -0
- package/dist/data/supabase.d.ts.map +1 -0
- package/dist/data/types.d.ts +22 -0
- package/dist/data/types.d.ts.map +1 -0
- package/dist/index.cjs +2936 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.ts +48 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +2930 -0
- package/dist/index.js.map +1 -0
- package/dist/lib/tenant.d.ts +3 -0
- package/dist/lib/tenant.d.ts.map +1 -0
- package/dist/locales/en.d.ts +2 -0
- package/dist/locales/en.d.ts.map +1 -0
- package/dist/locales/index.d.ts +2 -0
- package/dist/locales/index.d.ts.map +1 -0
- package/dist/locales/pt-BR.d.ts +2 -0
- package/dist/locales/pt-BR.d.ts.map +1 -0
- package/dist/registries.d.ts +3 -0
- package/dist/registries.d.ts.map +1 -0
- package/dist/store.d.ts +28 -0
- package/dist/store.d.ts.map +1 -0
- package/dist/types.d.ts +213 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/views/DashboardView.d.ts +8 -0
- package/dist/views/DashboardView.d.ts.map +1 -0
- package/dist/views/MovementHistoryView.d.ts +5 -0
- package/dist/views/MovementHistoryView.d.ts.map +1 -0
- package/dist/views/ProductCrudForm.d.ts +6 -0
- package/dist/views/ProductCrudForm.d.ts.map +1 -0
- package/dist/views/ProductFormView.d.ts +6 -0
- package/dist/views/ProductFormView.d.ts.map +1 -0
- package/dist/views/ProductListView.d.ts +6 -0
- package/dist/views/ProductListView.d.ts.map +1 -0
- package/dist/views/RecipeDetailView.d.ts +6 -0
- package/dist/views/RecipeDetailView.d.ts.map +1 -0
- package/dist/views/RecipeFormView.d.ts +5 -0
- package/dist/views/RecipeFormView.d.ts.map +1 -0
- package/dist/views/RecipesView.d.ts +6 -0
- package/dist/views/RecipesView.d.ts.map +1 -0
- package/dist/views/StockMovementView.d.ts +8 -0
- package/dist/views/StockMovementView.d.ts.map +1 -0
- package/dist/views/dashboardWidgets.d.ts +11 -0
- package/dist/views/dashboardWidgets.d.ts.map +1 -0
- package/dist/views/productEntity.d.ts +6 -0
- package/dist/views/productEntity.d.ts.map +1 -0
- package/package.json +55 -0
- package/src/InventoryContext.tsx +40 -0
- package/src/InventoryPage.tsx +170 -0
- package/src/README.md +177 -0
- package/src/components/InventoryGeneralSettings.tsx +26 -0
- package/src/components/InventoryOnboarding.tsx +60 -0
- package/src/components/InventorySettings.tsx +27 -0
- package/src/data/index.ts +2 -0
- package/src/data/mock.ts +266 -0
- package/src/data/supabase.ts +358 -0
- package/src/data/types.ts +35 -0
- package/src/index.ts +191 -0
- package/src/lib/tenant.ts +4 -0
- package/src/locales/en.ts +242 -0
- package/src/locales/index.ts +7 -0
- package/src/locales/pt-BR.ts +242 -0
- package/src/migrations/001_inventory_base.sql +69 -0
- package/src/migrations/002_recipes.sql +34 -0
- package/src/migrations/003_measurement_units.sql +13 -0
- package/src/registries.ts +111 -0
- package/src/store.ts +127 -0
- package/src/types.ts +256 -0
- package/src/views/DashboardView.tsx +11 -0
- package/src/views/MovementHistoryView.tsx +104 -0
- package/src/views/ProductCrudForm.tsx +99 -0
- package/src/views/ProductFormView.tsx +283 -0
- package/src/views/ProductListView.tsx +107 -0
- package/src/views/RecipeDetailView.tsx +192 -0
- package/src/views/RecipeFormView.tsx +235 -0
- package/src/views/RecipesView.tsx +103 -0
- package/src/views/StockMovementView.tsx +516 -0
- package/src/views/dashboardWidgets.tsx +101 -0
- package/src/views/productEntity.tsx +124 -0
package/src/index.ts
ADDED
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
import React from 'react'
|
|
2
|
+
import type { PluginManifest, PluginScope, VerticalId } from '@fayz-ai/core'
|
|
3
|
+
import { InventoryPage } from './InventoryPage'
|
|
4
|
+
import { createInventoryDashboardWidgets } from './views/dashboardWidgets'
|
|
5
|
+
import type { ResolvedInventoryConfig } from './InventoryContext'
|
|
6
|
+
import type { InventoryDataProvider } from './data/types'
|
|
7
|
+
import { createMockInventoryProvider } from './data/mock'
|
|
8
|
+
import { createSupabaseInventoryProvider } from './data/supabase'
|
|
9
|
+
import { createSafeDataProvider, registerTranslations } from '@fayz-ai/core'
|
|
10
|
+
import { createInventoryStore } from './store'
|
|
11
|
+
import { inventoryRegistries } from './registries'
|
|
12
|
+
import { inventoryLocales } from './locales'
|
|
13
|
+
import { InventoryGeneralSettings } from './components/InventoryGeneralSettings'
|
|
14
|
+
|
|
15
|
+
// ---------------------------------------------------------------------------
|
|
16
|
+
// Public types
|
|
17
|
+
// ---------------------------------------------------------------------------
|
|
18
|
+
|
|
19
|
+
export interface InventoryPluginLabels {
|
|
20
|
+
pageTitle: string
|
|
21
|
+
pageSubtitle: string
|
|
22
|
+
dashboard: string
|
|
23
|
+
products: string
|
|
24
|
+
productsNew: string
|
|
25
|
+
productsList: string
|
|
26
|
+
stock: string
|
|
27
|
+
stockEntry: string
|
|
28
|
+
stockExit: string
|
|
29
|
+
stockHistory: string
|
|
30
|
+
recipes: string
|
|
31
|
+
recipesNew: string
|
|
32
|
+
recipesList: string
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export interface InventoryPluginOptions {
|
|
36
|
+
modules?: {
|
|
37
|
+
recipes?: boolean
|
|
38
|
+
stockLocations?: boolean
|
|
39
|
+
batchTracking?: boolean
|
|
40
|
+
}
|
|
41
|
+
labels?: Partial<InventoryPluginLabels>
|
|
42
|
+
productTypes?: Array<{ value: string; label: string }>
|
|
43
|
+
currency?: { code?: string; locale?: string; symbol?: string }
|
|
44
|
+
navPosition?: number
|
|
45
|
+
navSection?: 'main' | 'secondary'
|
|
46
|
+
scope?: PluginScope
|
|
47
|
+
verticalId?: VerticalId
|
|
48
|
+
dataProvider?: InventoryDataProvider
|
|
49
|
+
locations?: Array<{ id: string; name: string; isHQ?: boolean }>
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// ---------------------------------------------------------------------------
|
|
53
|
+
// Defaults
|
|
54
|
+
// ---------------------------------------------------------------------------
|
|
55
|
+
|
|
56
|
+
const DEFAULT_LABELS: InventoryPluginLabels = {
|
|
57
|
+
pageTitle: 'Inventory',
|
|
58
|
+
pageSubtitle: 'Product catalog and stock management',
|
|
59
|
+
dashboard: 'Dashboard',
|
|
60
|
+
products: 'Products',
|
|
61
|
+
productsNew: 'New',
|
|
62
|
+
productsList: 'List',
|
|
63
|
+
stock: 'Stock',
|
|
64
|
+
stockEntry: 'Entry',
|
|
65
|
+
stockExit: 'Exit',
|
|
66
|
+
stockHistory: 'History',
|
|
67
|
+
recipes: 'Recipes',
|
|
68
|
+
recipesNew: 'New',
|
|
69
|
+
recipesList: 'List',
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
const DEFAULT_CURRENCY = { code: 'BRL', locale: 'pt-BR', symbol: 'R$' }
|
|
73
|
+
|
|
74
|
+
const DEFAULT_PRODUCT_TYPES = [
|
|
75
|
+
{ value: 'ingredient', label: 'Ingredient' },
|
|
76
|
+
{ value: 'sale', label: 'For Sale' },
|
|
77
|
+
{ value: 'intermediate', label: 'Intermediate' },
|
|
78
|
+
{ value: 'asset', label: 'Asset' },
|
|
79
|
+
]
|
|
80
|
+
|
|
81
|
+
// ---------------------------------------------------------------------------
|
|
82
|
+
// Config resolver
|
|
83
|
+
// ---------------------------------------------------------------------------
|
|
84
|
+
|
|
85
|
+
function resolveConfig(options?: InventoryPluginOptions): ResolvedInventoryConfig {
|
|
86
|
+
return {
|
|
87
|
+
modules: {
|
|
88
|
+
recipes: options?.modules?.recipes !== false,
|
|
89
|
+
stockLocations: options?.modules?.stockLocations !== false,
|
|
90
|
+
batchTracking: options?.modules?.batchTracking ?? false,
|
|
91
|
+
},
|
|
92
|
+
labels: { ...DEFAULT_LABELS, ...options?.labels },
|
|
93
|
+
currency: { ...DEFAULT_CURRENCY, ...options?.currency },
|
|
94
|
+
productTypes: options?.productTypes ?? DEFAULT_PRODUCT_TYPES,
|
|
95
|
+
locations: options?.locations ?? [],
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
// ---------------------------------------------------------------------------
|
|
100
|
+
// Factory
|
|
101
|
+
// ---------------------------------------------------------------------------
|
|
102
|
+
|
|
103
|
+
export function createInventoryPlugin(options?: InventoryPluginOptions): PluginManifest {
|
|
104
|
+
const config = resolveConfig(options)
|
|
105
|
+
registerTranslations(inventoryLocales)
|
|
106
|
+
const provider = options?.dataProvider ?? createSafeDataProvider(
|
|
107
|
+
() => createSupabaseInventoryProvider(),
|
|
108
|
+
() => createMockInventoryProvider(),
|
|
109
|
+
)
|
|
110
|
+
const store = createInventoryStore(provider)
|
|
111
|
+
const dashboardWidgets = createInventoryDashboardWidgets({ config, provider, store })
|
|
112
|
+
|
|
113
|
+
const PageComponent: React.FC<any> = () =>
|
|
114
|
+
React.createElement(InventoryPage, { config, provider, store, registries: inventoryRegistries })
|
|
115
|
+
|
|
116
|
+
return {
|
|
117
|
+
id: 'inventory',
|
|
118
|
+
name: config.labels.pageTitle,
|
|
119
|
+
icon: 'Package',
|
|
120
|
+
version: '1.0.0',
|
|
121
|
+
scope: options?.scope ?? 'universal',
|
|
122
|
+
verticalId: options?.verticalId,
|
|
123
|
+
defaultEnabled: true,
|
|
124
|
+
dependencies: [],
|
|
125
|
+
declaredFeatures: [
|
|
126
|
+
{ id: 'inventory', label: config.labels.pageTitle, group: config.labels.pageTitle },
|
|
127
|
+
...(config.modules.recipes ? [{ id: 'inventory.recipes', label: config.labels.recipes ?? 'Recipes', group: config.labels.pageTitle }] : []),
|
|
128
|
+
],
|
|
129
|
+
navigation: [
|
|
130
|
+
{
|
|
131
|
+
section: options?.navSection ?? 'main',
|
|
132
|
+
position: options?.navPosition ?? 4,
|
|
133
|
+
label: config.labels.pageTitle,
|
|
134
|
+
route: '/inventory',
|
|
135
|
+
icon: 'Package',
|
|
136
|
+
permission: { feature: 'inventory', action: 'read' as const },
|
|
137
|
+
},
|
|
138
|
+
],
|
|
139
|
+
routes: [
|
|
140
|
+
{
|
|
141
|
+
path: '/inventory',
|
|
142
|
+
component: PageComponent,
|
|
143
|
+
permission: { feature: 'inventory', action: 'read' as const },
|
|
144
|
+
},
|
|
145
|
+
],
|
|
146
|
+
widgets: [],
|
|
147
|
+
dashboardWidgets,
|
|
148
|
+
aiTools: [
|
|
149
|
+
{
|
|
150
|
+
id: 'inventory.low-stock',
|
|
151
|
+
name: 'getLowStock',
|
|
152
|
+
description: 'Lists products with stock below minimum threshold.',
|
|
153
|
+
icon: 'AlertTriangle',
|
|
154
|
+
mode: 'read' as const,
|
|
155
|
+
category: 'Inventory',
|
|
156
|
+
parameters: {
|
|
157
|
+
type: 'object' as const,
|
|
158
|
+
properties: {
|
|
159
|
+
threshold: { type: 'number' as const, description: 'Custom stock threshold' },
|
|
160
|
+
},
|
|
161
|
+
},
|
|
162
|
+
suggestions: [
|
|
163
|
+
{ label: 'Which products are running low?' },
|
|
164
|
+
{ label: 'What ingredients need restocking?', verticalId: 'food' as const },
|
|
165
|
+
{ label: 'Show me a stock summary' },
|
|
166
|
+
{ label: 'What are my most used products?' },
|
|
167
|
+
],
|
|
168
|
+
permission: { feature: 'inventory', action: 'read' as const },
|
|
169
|
+
},
|
|
170
|
+
],
|
|
171
|
+
registries: inventoryRegistries,
|
|
172
|
+
settings: [
|
|
173
|
+
{
|
|
174
|
+
id: 'inventory',
|
|
175
|
+
label: 'Inventory',
|
|
176
|
+
icon: 'Package',
|
|
177
|
+
component: (() => {
|
|
178
|
+
const Tab: React.FC = () => React.createElement(InventoryGeneralSettings)
|
|
179
|
+
Tab.displayName = 'InventorySettingsTab'
|
|
180
|
+
return Tab
|
|
181
|
+
})() as unknown as React.ComponentType<unknown>,
|
|
182
|
+
order: 11,
|
|
183
|
+
permission: { feature: 'inventory', action: 'read' as const },
|
|
184
|
+
},
|
|
185
|
+
],
|
|
186
|
+
locales: inventoryLocales,
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
export type { InventoryDataProvider } from './data/types'
|
|
191
|
+
export type { ResolvedInventoryConfig } from './InventoryContext'
|
|
@@ -0,0 +1,242 @@
|
|
|
1
|
+
// inventory.* — merged plugin-own + saas-core central i18n
|
|
2
|
+
export const en: Record<string, string> = {
|
|
3
|
+
"inventory.dashboard.activeItems": "Active items",
|
|
4
|
+
"inventory.dashboard.belowMinimum": "Below minimum",
|
|
5
|
+
"inventory.dashboard.entries": "Entries:",
|
|
6
|
+
"inventory.dashboard.exits": "Exits:",
|
|
7
|
+
"inventory.dashboard.last7Days": "Last 7 days",
|
|
8
|
+
"inventory.dashboard.lowStock": "Low Stock",
|
|
9
|
+
"inventory.dashboard.needRestocking": "Need restocking",
|
|
10
|
+
"inventory.dashboard.outOfStock": "Out of Stock",
|
|
11
|
+
"inventory.dashboard.quickActions": "Quick Actions",
|
|
12
|
+
"inventory.dashboard.quickActionsDesc": "Use the sidebar to record stock entries, exits, or manage products.",
|
|
13
|
+
"inventory.dashboard.recentActivity": "Recent Activity",
|
|
14
|
+
"inventory.dashboard.stockValue": "Stock Value",
|
|
15
|
+
"inventory.dashboard.totalProducts": "Total Products",
|
|
16
|
+
"inventory.dashboard.totalValue": "Total inventory value",
|
|
17
|
+
"inventory.history.noMovements": "No movements recorded",
|
|
18
|
+
"inventory.history.searchPlaceholder": "Search movements...",
|
|
19
|
+
"inventory.history.subtitle": "All stock movements",
|
|
20
|
+
"inventory.history.title": "Stock History",
|
|
21
|
+
"inventory.nav.dashboard": "Dashboard",
|
|
22
|
+
"inventory.nav.entry": "Entry",
|
|
23
|
+
"inventory.nav.exit": "Exit",
|
|
24
|
+
"inventory.nav.history": "History",
|
|
25
|
+
"inventory.nav.list": "List",
|
|
26
|
+
"inventory.nav.new": "New",
|
|
27
|
+
"inventory.nav.products": "Products",
|
|
28
|
+
"inventory.nav.stock": "Stock",
|
|
29
|
+
"inventory.page.newProduct": "New Product",
|
|
30
|
+
"inventory.page.newProductDesc": "Add a product to your catalog",
|
|
31
|
+
"inventory.page.settingsSubtitle": "Preferences, suppliers, categories, and units",
|
|
32
|
+
"inventory.page.settingsTitle": "Inventory Settings",
|
|
33
|
+
"inventory.page.stockEntry": "Stock Entry",
|
|
34
|
+
"inventory.page.stockEntryDesc": "Record goods received",
|
|
35
|
+
"inventory.page.stockExit": "Stock Exit",
|
|
36
|
+
"inventory.page.stockExitDesc": "Record goods used or sold",
|
|
37
|
+
"inventory.recipeDetail.active": "Active",
|
|
38
|
+
"inventory.recipeDetail.backToList": "Back to list",
|
|
39
|
+
"inventory.recipeDetail.inactive": "Inactive",
|
|
40
|
+
"inventory.recipeDetail.ingredientCount": "Ingredients",
|
|
41
|
+
"inventory.recipeDetail.ingredientsTitle": "Ingredients",
|
|
42
|
+
"inventory.recipeDetail.instructions": "Instructions",
|
|
43
|
+
"inventory.recipeDetail.noIngredients": "No ingredients defined",
|
|
44
|
+
"inventory.recipeDetail.notFound": "Recipe not found",
|
|
45
|
+
"inventory.recipeDetail.prepTime": "Prep time",
|
|
46
|
+
"inventory.recipeDetail.produces": "Produces",
|
|
47
|
+
"inventory.recipeDetail.recipes": "Recipes",
|
|
48
|
+
"inventory.recipeDetail.yield": "Yield",
|
|
49
|
+
"inventory.recipes.createFirst": "Create your first recipe",
|
|
50
|
+
"inventory.recipes.ingredients": "Ingredients",
|
|
51
|
+
"inventory.recipes.newRecipe": "New Recipe",
|
|
52
|
+
"inventory.recipes.noRecipes": "No recipes yet",
|
|
53
|
+
"inventory.recipes.produces": "Produces:",
|
|
54
|
+
"inventory.recipes.productionFormulas": "{{count}} production formulas",
|
|
55
|
+
"inventory.recipes.recipesDesc": "Recipes define how to produce products from ingredients",
|
|
56
|
+
"inventory.recipes.title": "Recipes",
|
|
57
|
+
"inventory.recipes.yield": "Yield",
|
|
58
|
+
"inventory.stock.additionalDetails": "Additional details (optional)",
|
|
59
|
+
"inventory.stock.adjustmentDesc": "Count correction",
|
|
60
|
+
"inventory.stock.adjustmentLabel": "Adjustment",
|
|
61
|
+
"inventory.stock.back": "Back",
|
|
62
|
+
"inventory.stock.batchNumber": "Batch Number",
|
|
63
|
+
"inventory.stock.currentStock": "Current Stock",
|
|
64
|
+
"inventory.stock.destination": "Destination",
|
|
65
|
+
"inventory.stock.document": "Document",
|
|
66
|
+
"inventory.stock.documentNumber": "Document Number",
|
|
67
|
+
"inventory.stock.entry": "Stock Entry",
|
|
68
|
+
"inventory.stock.entryDesc": "Receiving goods",
|
|
69
|
+
"inventory.stock.entryLabel": "Entry",
|
|
70
|
+
"inventory.stock.exit": "Stock Exit",
|
|
71
|
+
"inventory.stock.exitDesc": "Using or selling",
|
|
72
|
+
"inventory.stock.exitLabel": "Exit",
|
|
73
|
+
"inventory.stock.expirationDate": "Expiration Date",
|
|
74
|
+
"inventory.stock.fromLocation": "From Location",
|
|
75
|
+
"inventory.stock.locationLabel": "Location",
|
|
76
|
+
"inventory.stock.lossDesc": "Waste or damage",
|
|
77
|
+
"inventory.stock.lossLabel": "Loss",
|
|
78
|
+
"inventory.stock.movement": "Stock Movement",
|
|
79
|
+
"inventory.stock.movementDetails": "Movement Details",
|
|
80
|
+
"inventory.stock.movementType": "Movement type",
|
|
81
|
+
"inventory.stock.next": "Next",
|
|
82
|
+
"inventory.stock.notes": "Notes",
|
|
83
|
+
"inventory.stock.product": "Product",
|
|
84
|
+
"inventory.stock.quantity": "Quantity *",
|
|
85
|
+
"inventory.stock.quantityLabel": "Quantity",
|
|
86
|
+
"inventory.stock.reason": "Reason *",
|
|
87
|
+
"inventory.stock.reasonLabel": "Reason",
|
|
88
|
+
"inventory.stock.recordMovement": "Record Movement",
|
|
89
|
+
"inventory.stock.recorded": "Recorded",
|
|
90
|
+
"inventory.stock.recording": "Recording...",
|
|
91
|
+
"inventory.stock.searchProduct": "Search by name, SKU, or barcode...",
|
|
92
|
+
"inventory.stock.stepOf": "Step {{step}} of 3",
|
|
93
|
+
"inventory.stock.supplier": "Supplier",
|
|
94
|
+
"inventory.stock.toLocation": "To Location *",
|
|
95
|
+
"inventory.stock.total": "Total",
|
|
96
|
+
"inventory.stock.totalCost": "Total Cost",
|
|
97
|
+
"inventory.stock.transferDesc": "Between locations",
|
|
98
|
+
"inventory.stock.transferLabel": "Transfer",
|
|
99
|
+
"inventory.stock.unitCost": "Unit Cost",
|
|
100
|
+
"inventory.stock.unitCostLabel": "Unit Cost",
|
|
101
|
+
"inventory.onboarding.welcome": "Welcome to Inventory",
|
|
102
|
+
"inventory.onboarding.description": "Track products, manage stock levels, and monitor movements across your business.",
|
|
103
|
+
"inventory.onboarding.skip": "Skip setup",
|
|
104
|
+
"inventory.onboarding.getStarted": "Get Started",
|
|
105
|
+
"inventory.onboarding.units.title": "Measurement Units",
|
|
106
|
+
"inventory.onboarding.units.description": "Default units (Unit, Box, Kg, L, etc.) are ready. Customize them anytime in Settings.",
|
|
107
|
+
"inventory.onboarding.locations.title": "Stock Locations",
|
|
108
|
+
"inventory.onboarding.locations.description": "A default storage location has been created. Add more for multi-location tracking.",
|
|
109
|
+
"inventory.onboarding.start": "Start using Inventory",
|
|
110
|
+
"inventory.quickActions.newProduct": "New Product",
|
|
111
|
+
"inventory.quickActions.newProductDesc": "Add a product to your catalog",
|
|
112
|
+
"inventory.quickActions.stockEntry": "Stock Entry",
|
|
113
|
+
"inventory.quickActions.stockEntryDesc": "Record goods received",
|
|
114
|
+
"inventory.quickActions.stockExit": "Stock Exit",
|
|
115
|
+
"inventory.quickActions.stockExitDesc": "Record goods used or sold",
|
|
116
|
+
"inventory.settingsPage.title": "Inventory Settings",
|
|
117
|
+
"inventory.settingsPage.subtitle": "Manage units, categories, and stock locations",
|
|
118
|
+
"inventory.settings.stockManagement": "Stock Management",
|
|
119
|
+
"inventory.settings.stockManagementDesc": "How stock levels are tracked",
|
|
120
|
+
"inventory.settings.lowStockAlerts": "Low stock alerts",
|
|
121
|
+
"inventory.settings.lowStockAlertsDesc": "Show warnings when products fall below minimum quantity",
|
|
122
|
+
"inventory.settings.requireReason": "Require reason for adjustments",
|
|
123
|
+
"inventory.settings.requireReasonDesc": "Make reason mandatory for stock adjustments and losses",
|
|
124
|
+
"inventory.settings.autoDeduct": "Auto-deduct on service",
|
|
125
|
+
"inventory.settings.autoDeductDesc": "Automatically deduct products when a service is executed",
|
|
126
|
+
"inventory.settings.products": "Products",
|
|
127
|
+
"inventory.settings.productsDesc": "Product catalog behavior",
|
|
128
|
+
"inventory.settings.requireSku": "Require SKU",
|
|
129
|
+
"inventory.settings.requireSkuDesc": "Make SKU mandatory when creating products",
|
|
130
|
+
"inventory.settings.allowNegative": "Allow negative stock",
|
|
131
|
+
"inventory.settings.allowNegativeDesc": "Allow stock quantities to go below zero",
|
|
132
|
+
"inventory.settings.notifications": "Notifications",
|
|
133
|
+
"inventory.settings.notificationsDesc": "Alerts and reminders",
|
|
134
|
+
"inventory.settings.lowStockEmail": "Low stock email alerts",
|
|
135
|
+
"inventory.settings.lowStockEmailDesc": "Send email when products reach minimum quantity",
|
|
136
|
+
"inventory.settings.expiryWarnings": "Expiry date warnings",
|
|
137
|
+
"inventory.settings.expiryWarningsDesc": "Alert before products expire (batch tracking)",
|
|
138
|
+
"inventory.productForm.newProduct": "New Product",
|
|
139
|
+
"inventory.productForm.editProduct": "Edit Product",
|
|
140
|
+
"inventory.productForm.updateDetails": "Update product details",
|
|
141
|
+
"inventory.productForm.addToCatalog": "Add a product to your catalog",
|
|
142
|
+
"inventory.productForm.cancel": "Cancel",
|
|
143
|
+
"inventory.productForm.save": "Save",
|
|
144
|
+
"inventory.productForm.saving": "Saving...",
|
|
145
|
+
"inventory.productForm.generalInfo": "General Information",
|
|
146
|
+
"inventory.productForm.name": "Name",
|
|
147
|
+
"inventory.productForm.namePlaceholder": "Product name",
|
|
148
|
+
"inventory.productForm.brand": "Brand",
|
|
149
|
+
"inventory.productForm.brandPlaceholder": "Brand name",
|
|
150
|
+
"inventory.productForm.sku": "SKU",
|
|
151
|
+
"inventory.productForm.skuPlaceholder": "Internal code",
|
|
152
|
+
"inventory.productForm.barcode": "Barcode",
|
|
153
|
+
"inventory.productForm.barcodePlaceholder": "EAN / UPC",
|
|
154
|
+
"inventory.productForm.description": "Description",
|
|
155
|
+
"inventory.productForm.descriptionPlaceholder": "Additional information about the product",
|
|
156
|
+
"inventory.productForm.classification": "Classification",
|
|
157
|
+
"inventory.productForm.classificationDesc": "How this product is used in your business",
|
|
158
|
+
"inventory.productForm.typeIngredient": "Raw material used in production or services",
|
|
159
|
+
"inventory.productForm.typeSale": "Sold directly to customers",
|
|
160
|
+
"inventory.productForm.typeIntermediate": "Produced internally from other items",
|
|
161
|
+
"inventory.productForm.typeAsset": "Fixed asset for patrimony tracking",
|
|
162
|
+
"inventory.productForm.pricing": "Pricing",
|
|
163
|
+
"inventory.productForm.costPrice": "Cost Price",
|
|
164
|
+
"inventory.productForm.salePrice": "Sale Price",
|
|
165
|
+
"inventory.productForm.margin": "Margin",
|
|
166
|
+
"inventory.productForm.stockLevels": "Stock Levels",
|
|
167
|
+
"inventory.productForm.stockLevelsDesc": "Minimum and maximum thresholds for alerts",
|
|
168
|
+
"inventory.productForm.minQuantity": "Minimum Quantity",
|
|
169
|
+
"inventory.productForm.minQuantityHint": "Alert when stock falls below this",
|
|
170
|
+
"inventory.productForm.maxQuantity": "Maximum Quantity",
|
|
171
|
+
"inventory.productForm.maxQuantityHint": "Max capacity for this product",
|
|
172
|
+
"inventory.productForm.optional": "Optional",
|
|
173
|
+
"inventory.productList.title": "Products",
|
|
174
|
+
"inventory.productList.subtitle": "{{count}} products",
|
|
175
|
+
"inventory.productList.product": "Product",
|
|
176
|
+
"inventory.productList.type": "Type",
|
|
177
|
+
"inventory.productList.stock": "Stock",
|
|
178
|
+
"inventory.productList.cost": "Cost",
|
|
179
|
+
"inventory.productList.value": "Value",
|
|
180
|
+
"inventory.productList.searchPlaceholder": "Search products...",
|
|
181
|
+
"inventory.productList.newProduct": "New Product",
|
|
182
|
+
"inventory.productList.empty": "No products yet",
|
|
183
|
+
"inventory.productList.createFirst": "Create your first product",
|
|
184
|
+
"inventory.stock.unknownProduct": "Unknown Product",
|
|
185
|
+
"inventory.stock.reasonLossPlaceholder": "e.g. Expired, damaged",
|
|
186
|
+
"inventory.stock.reasonAdjustPlaceholder": "e.g. Physical count correction",
|
|
187
|
+
"inventory.stock.documentPlaceholder": "Invoice, receipt, PO...",
|
|
188
|
+
"inventory.stock.batchPlaceholder": "e.g. LOT001",
|
|
189
|
+
"inventory.stock.notesPlaceholder": "Additional notes...",
|
|
190
|
+
"inventory.recipeDetail.loading": "Loading...",
|
|
191
|
+
"inventory.recipeDetail.ingredient": "Ingredient",
|
|
192
|
+
"inventory.recipeDetail.quantity": "Quantity",
|
|
193
|
+
"inventory.recipeDetail.unit": "Unit",
|
|
194
|
+
"inventory.recipeDetail.notes": "Notes",
|
|
195
|
+
"inventory.recipeDetail.created": "Created",
|
|
196
|
+
"inventory.recipeDetail.updated": "Updated",
|
|
197
|
+
"inventory.recipeForm.newRecipe": "New Recipe",
|
|
198
|
+
"inventory.recipeForm.subtitle": "Define a production formula",
|
|
199
|
+
"inventory.recipeForm.cancel": "Cancel",
|
|
200
|
+
"inventory.recipeForm.saveRecipe": "Save Recipe",
|
|
201
|
+
"inventory.recipeForm.saving": "Saving...",
|
|
202
|
+
"inventory.recipeForm.recipeDetails": "Recipe Details",
|
|
203
|
+
"inventory.recipeForm.recipeName": "Recipe Name",
|
|
204
|
+
"inventory.recipeForm.recipeNamePlaceholder": "e.g. Tomato Sauce",
|
|
205
|
+
"inventory.recipeForm.description": "Description",
|
|
206
|
+
"inventory.recipeForm.descriptionPlaceholder": "Brief description...",
|
|
207
|
+
"inventory.recipeForm.produces": "Produces (Product)",
|
|
208
|
+
"inventory.recipeForm.searchProduct": "Search product...",
|
|
209
|
+
"inventory.recipeForm.createProduct": "Create product",
|
|
210
|
+
"inventory.recipeForm.yieldQuantity": "Yield Quantity",
|
|
211
|
+
"inventory.recipeForm.prepTime": "Prep Time (min)",
|
|
212
|
+
"inventory.recipeForm.instructions": "Instructions",
|
|
213
|
+
"inventory.recipeForm.instructionsPlaceholder": "Step-by-step preparation instructions...",
|
|
214
|
+
"inventory.recipeForm.ingredients": "Ingredients",
|
|
215
|
+
"inventory.recipeForm.addIngredient": "Add Ingredient",
|
|
216
|
+
"inventory.recipeForm.noIngredients": "No ingredients added",
|
|
217
|
+
"inventory.recipeForm.addFirstIngredient": "Add your first ingredient",
|
|
218
|
+
"inventory.recipeForm.ingredient": "Ingredient",
|
|
219
|
+
"inventory.recipeForm.quantity": "Quantity",
|
|
220
|
+
"inventory.recipeForm.notes": "Notes",
|
|
221
|
+
"inventory.recipeForm.searchIngredient": "Search ingredient...",
|
|
222
|
+
"inventory.recipeForm.createIngredient": "Create ingredient",
|
|
223
|
+
"inventory.recipeForm.notesPlaceholder": "e.g. diced, fresh",
|
|
224
|
+
"inventory.recipeForm.ingredientsConfigured": "{{configured}} of {{total}} ingredients configured",
|
|
225
|
+
"inventory.title": "Inventory",
|
|
226
|
+
"inventory.stock.title": "Stock",
|
|
227
|
+
"inventory.stock.minStock": "Min. Stock",
|
|
228
|
+
"inventory.stock.adjust": "Adjust Stock",
|
|
229
|
+
"inventory.stock.lowStock": "Low Stock",
|
|
230
|
+
"inventory.products.title": "Products",
|
|
231
|
+
"inventory.products.create": "New Product",
|
|
232
|
+
"inventory.recipes.create": "New Recipe",
|
|
233
|
+
"inventory.recipes.addIngredient": "Add Ingredient",
|
|
234
|
+
"inventory.recipes.cost": "Cost",
|
|
235
|
+
"inventory.recipes.loading": "Loading...",
|
|
236
|
+
"inventory.suppliers.title": "Suppliers",
|
|
237
|
+
"inventory.suppliers.create": "New Supplier",
|
|
238
|
+
"inventory.movements.title": "Movements",
|
|
239
|
+
"inventory.movements.in": "Stock In",
|
|
240
|
+
"inventory.movements.out": "Stock Out",
|
|
241
|
+
"inventory.settings.title": "Inventory Settings",
|
|
242
|
+
}
|