diff --git a/backend/patches/addUOMs.ts b/backend/patches/addUOMs.ts index d53329e7..b8b5c652 100644 --- a/backend/patches/addUOMs.ts +++ b/backend/patches/addUOMs.ts @@ -1,8 +1,34 @@ import { ModelNameEnum } from '../../models/types'; -import { defaultUOMs } from '../../utils/defaults'; import { DatabaseManager } from '../database/manager'; import { getDefaultMetaFieldValueMap } from '../helpers'; +const defaultUOMs = [ + { + name: `Unit`, + isWhole: true, + }, + { + name: `Kg`, + isWhole: false, + }, + { + name: `Gram`, + isWhole: false, + }, + { + name: `Meter`, + isWhole: false, + }, + { + name: `Hour`, + isWhole: false, + }, + { + name: `Day`, + isWhole: false, + }, +]; + async function execute(dm: DatabaseManager) { for (const uom of defaultUOMs) { const defaults = getDefaultMetaFieldValueMap(); diff --git a/models/inventory/InventorySettings.ts b/models/inventory/InventorySettings.ts index 1bcd6c0a..eee67389 100644 --- a/models/inventory/InventorySettings.ts +++ b/models/inventory/InventorySettings.ts @@ -4,6 +4,7 @@ import { AccountTypeEnum } from 'models/baseModels/Account/types'; import { ValuationMethod } from './types'; export class InventorySettings extends Doc { + defaultLocation?: string; stockInHand?: string; valuationMethod?: ValuationMethod; stockReceivedButNotBilled?: string; diff --git a/models/inventory/StockMovementItem.ts b/models/inventory/StockMovementItem.ts index 9a70b38c..665852a1 100644 --- a/models/inventory/StockMovementItem.ts +++ b/models/inventory/StockMovementItem.ts @@ -3,11 +3,10 @@ import { FiltersMap, FormulaMap, ReadOnlyMap, - RequiredMap + RequiredMap, } from 'fyo/model/types'; import { ModelNameEnum } from 'models/types'; import { Money } from 'pesa'; -import { locationFilter } from './helpers'; import { StockMovement } from './StockMovement'; import { MovementType } from './types'; @@ -21,10 +20,20 @@ export class StockMovementItem extends Doc { amount?: Money; parentdoc?: StockMovement; + get isIssue() { + return this.parentdoc?.movementType === MovementType.MaterialIssue; + } + + get isReceipt() { + return this.parentdoc?.movementType === MovementType.MaterialReceipt; + } + + get isTransfer() { + return this.parentdoc?.movementType === MovementType.MaterialTransfer; + } + static filters: FiltersMap = { item: () => ({ trackItem: true }), - toLocation: locationFilter, - fromLocation: locationFilter, }; formulas: FormulaMap = { @@ -43,40 +52,50 @@ export class StockMovementItem extends Doc { dependsOn: ['item', 'rate', 'quantity'], }, fromLocation: { - formula: () => { - if (this.parentdoc?.movementType === MovementType.MaterialReceipt) { + formula: (fn) => { + if (this.isReceipt || this.isTransfer) { return null; } + + const defaultLocation = this.fyo.singles.InventorySettings + ?.defaultLocation as string | undefined; + if (defaultLocation && !this.location && this.isIssue) { + return defaultLocation; + } + + return this.toLocation; }, + dependsOn: ['movementType'], }, toLocation: { - formula: () => { - if (this.parentdoc?.movementType === MovementType.MaterialIssue) { + formula: (fn) => { + if (this.isIssue || this.isTransfer) { return null; } + + const defaultLocation = this.fyo.singles.InventorySettings + ?.defaultLocation as string | undefined; + if (defaultLocation && !this.location && this.isReceipt) { + return defaultLocation; + } + + return this.toLocation; }, + dependsOn: ['movementType'], }, }; required: RequiredMap = { - fromLocation: () => - this.parentdoc?.movementType === 'MaterialIssue' || - this.parentdoc?.movementType === 'MaterialTransfer', - toLocation: () => - this.parentdoc?.movementType === 'MaterialReceipt' || - this.parentdoc?.movementType === 'MaterialTransfer', + fromLocation: () => this.isIssue || this.isTransfer, + toLocation: () => this.isReceipt || this.isTransfer, }; readOnly: ReadOnlyMap = { - fromLocation: () => - this.parentdoc?.movementType === MovementType.MaterialReceipt, - toLocation: () => - this.parentdoc?.movementType === MovementType.MaterialIssue, + fromLocation: () => this.isReceipt, + toLocation: () => this.isIssue, }; static createFilters: FiltersMap = { item: () => ({ trackItem: true, itemType: 'Product' }), - fromLocation: (doc: Doc) => ({ item: (doc.item ?? '') as string }), - toLocation: (doc: Doc) => ({ item: (doc.item ?? '') as string }), }; } diff --git a/models/inventory/StockTransferItem.ts b/models/inventory/StockTransferItem.ts index e09f6bb6..9b12d208 100644 --- a/models/inventory/StockTransferItem.ts +++ b/models/inventory/StockTransferItem.ts @@ -2,7 +2,6 @@ import { Doc } from 'fyo/model/doc'; import { FiltersMap, FormulaMap } from 'fyo/model/types'; import { ModelNameEnum } from 'models/types'; import { Money } from 'pesa'; -import { locationFilter } from './helpers'; export class StockTransferItem extends Doc { item?: string; @@ -94,6 +93,20 @@ export class StockTransferItem extends Doc { }, dependsOn: ['item'], }, + location: { + formula: () => { + if (this.location) { + return; + } + + const defaultLocation = this.fyo.singles.InventorySettings + ?.defaultLocation as string | undefined; + + if (defaultLocation && !this.location) { + return defaultLocation; + } + }, + }, }; static filters: FiltersMap = { @@ -105,6 +118,5 @@ export class StockTransferItem extends Doc { return { for: ['not in', [itemNotFor]], trackItem: true }; }, - location: locationFilter, }; } diff --git a/models/inventory/helpers.ts b/models/inventory/helpers.ts index 24de3e98..8b137891 100644 --- a/models/inventory/helpers.ts +++ b/models/inventory/helpers.ts @@ -1,12 +1 @@ -import { Doc } from "fyo/model/doc"; -import { FilterFunction } from "fyo/model/types"; -import { QueryFilter } from "utils/db/types"; -export const locationFilter: FilterFunction = (doc: Doc) => { - const item = doc.item; - if (!doc.item) { - return { item: null }; - } - - return { item: ['in', [null, item]] } as QueryFilter; -}; diff --git a/schemas/app/inventory/InventorySettings.json b/schemas/app/inventory/InventorySettings.json index 3230a77e..0075ee47 100644 --- a/schemas/app/inventory/InventorySettings.json +++ b/schemas/app/inventory/InventorySettings.json @@ -21,6 +21,13 @@ "default": "FIFO", "required": true }, + { + "fieldname": "defaultLocation", + "label": "Default Location", + "fieldtype": "Link", + "target": "Location", + "create": true + }, { "fieldname": "stockInHand", "label": "Stock In Hand Acc.", diff --git a/schemas/app/inventory/Location.json b/schemas/app/inventory/Location.json index e25047be..6926aaee 100644 --- a/schemas/app/inventory/Location.json +++ b/schemas/app/inventory/Location.json @@ -12,11 +12,13 @@ "required": true }, { - "fieldname": "item", - "label": "Item", + "fieldname": "address", + "label": "Address", "fieldtype": "Link", - "target": "Item" + "target": "Address", + "placeholder": "Click to create", + "inline": true } ], - "quickEditFields": ["item"] + "quickEditFields": ["item", "address"] } diff --git a/src/setup/setupInstance.ts b/src/setup/setupInstance.ts index c626aed5..6937267a 100644 --- a/src/setup/setupInstance.ts +++ b/src/setup/setupInstance.ts @@ -7,7 +7,6 @@ import { DEFAULT_LOCALE, DEFAULT_SERIES_START, } from 'fyo/utils/consts'; -import { ValueError } from 'fyo/utils/errors'; import { AccountRootTypeEnum, AccountTypeEnum, @@ -23,7 +22,7 @@ import { setCurrencySymbols, } from 'src/utils/initialization'; import { getRandomString } from 'utils'; -import { defaultUOMs } from 'utils/defaults'; +import { getDefaultLocations, getDefaultUOMs } from 'utils/defaults'; import { getCountryCodeFromCountry, getCountryInfo } from 'utils/misc'; import { CountryInfo } from 'utils/types'; import { CreateCOA } from './createCOA'; @@ -62,9 +61,13 @@ async function createDefaultEntries(fyo: Fyo) { /** * Create default UOM entries */ - for (const uom of defaultUOMs) { + for (const uom of getDefaultUOMs(fyo)) { await checkAndCreateDoc(ModelNameEnum.UOM, uom, fyo); } + + for (const loc of getDefaultLocations(fyo)) { + await checkAndCreateDoc(ModelNameEnum.Location, loc, fyo); + } } async function initializeDatabase(dbPath: string, country: string, fyo: Fyo) { @@ -368,5 +371,10 @@ async function updateInventorySettings(fyo: Fyo) { inventorySettings.set(settingName, accounts[0].name); } + const location = fyo.t`Stores`; + if (await fyo.db.exists(ModelNameEnum.Location, location)) { + inventorySettings.set('defaultLocation', location); + } + await inventorySettings.sync(); } diff --git a/utils/defaults.ts b/utils/defaults.ts index 6bead525..be7cb8ec 100644 --- a/utils/defaults.ts +++ b/utils/defaults.ts @@ -1,26 +1,34 @@ -export const defaultUOMs = [ - { - name: 'Unit', - isWhole: true, - }, - { - name: 'Kg', - isWhole: false, - }, - { - name: 'Gram', - isWhole: false, - }, - { - name: 'Meter', - isWhole: false, - }, - { - name: 'Hour', - isWhole: false, - }, - { - name: 'Day', - isWhole: false, - }, -]; +import { Fyo } from 'fyo'; + +export function getDefaultUOMs(fyo: Fyo) { + return [ + { + name: fyo.t`Unit`, + isWhole: true, + }, + { + name: fyo.t`Kg`, + isWhole: false, + }, + { + name: fyo.t`Gram`, + isWhole: false, + }, + { + name: fyo.t`Meter`, + isWhole: false, + }, + { + name: fyo.t`Hour`, + isWhole: false, + }, + { + name: fyo.t`Day`, + isWhole: false, + }, + ]; +} + +export function getDefaultLocations(fyo: Fyo) { + return [{ name: fyo.t`Stores` }]; +}