2
0
mirror of https://github.com/frappe/books.git synced 2024-11-09 23:30:56 +00:00

incr: add inventory settings

This commit is contained in:
18alantom 2022-11-18 14:14:29 +05:30
parent b5f8e49299
commit 14138967c1
14 changed files with 187 additions and 51 deletions

View File

@ -43,16 +43,16 @@ export class Defaults extends Doc {
static filters: FiltersMap = this.commonFilters;
static createFilters: FiltersMap = this.commonFilters;
hideInventoryDefaults(): boolean {
return !this.fyo.store.appFlags.getIsInventoryEnabled;
getInventoryHidden() {
return () => !this.fyo.store.appFlags.isInventoryEnabled;
}
hidden: HiddenMap = {
stockMovementNumberSeries: this.hideInventoryDefaults.bind(this),
shipmentNumberSeries: this.hideInventoryDefaults.bind(this),
purchaseReceiptNumberSeries: this.hideInventoryDefaults.bind(this),
shipmentTerms: this.hideInventoryDefaults.bind(this),
purchaseReceiptTerms: this.hideInventoryDefaults.bind(this),
stockMovementNumberSeries: this.getInventoryHidden(),
shipmentNumberSeries: this.getInventoryHidden(),
purchaseReceiptNumberSeries: this.getInventoryHidden(),
shipmentTerms: this.getInventoryHidden(),
purchaseReceiptTerms: this.getInventoryHidden(),
};
}

View File

@ -17,6 +17,7 @@ import { SalesInvoiceItem } from './baseModels/SalesInvoiceItem/SalesInvoiceItem
import { SetupWizard } from './baseModels/SetupWizard/SetupWizard';
import { Tax } from './baseModels/Tax/Tax';
import { TaxSummary } from './baseModels/TaxSummary/TaxSummary';
import { InventorySettings } from './inventory/InventorySettings';
import { Location } from './inventory/Location';
import { PurchaseReceipt } from './inventory/PurchaseReceipt';
import { PurchaseReceiptItem } from './inventory/PurchaseReceiptItem';
@ -46,6 +47,7 @@ export const models = {
Tax,
TaxSummary,
// Inventory Models
InventorySettings,
StockMovement,
StockMovementItem,
StockLedgerEntry,

View File

@ -0,0 +1,21 @@
import { Doc } from 'fyo/model/doc';
import { FiltersMap } from 'fyo/model/types';
import { AccountTypeEnum } from 'models/baseModels/Account/types';
import { valuationMethod } from './types';
export class InventorySettings extends Doc {
stockInHand?: string;
valuationMethod?: valuationMethod;
stockInReceivedButNotBilled?: string;
static filters: FiltersMap = {
stockInHand: () => ({
isGroup: false,
accountType: AccountTypeEnum.Stock,
}),
stockReceivedButNotBilled: () => ({
isGroup: false,
accountType: AccountTypeEnum['Stock Received But Not Billed'],
}),
};
}

View File

@ -29,6 +29,7 @@ export enum ModelNameEnum {
TaxSummary = 'TaxSummary',
PatchRun = 'PatchRun',
SingleValue = 'SingleValue',
InventorySettings = 'InventorySettings',
SystemSettings = 'SystemSettings',
StockMovement = 'StockMovement',
StockMovementItem = 'StockMovementItem',

View File

@ -0,0 +1,39 @@
{
"name": "InventorySettings",
"label": "Inventory Settings",
"isSingle": true,
"isChild": false,
"fields": [
{
"fieldname": "valuationMethod",
"label": "Valuation Method",
"fieldtype": "Select",
"options": [
{
"value": "FIFO",
"label": "FIFO"
},
{
"value": "MovingAverage",
"label": "Moving Average"
}
],
"default": "FIFO",
"required": true
},
{
"fieldname": "stockInHand",
"label": "Stock In Hand Acc.",
"fieldtype": "Link",
"target": "Account",
"create": true
},
{
"fieldname": "stockReceivedButNotBilled",
"label": "Stock Received But Not Billed Acc.",
"fieldtype": "Link",
"target": "Account",
"create": true
}
]
}

View File

@ -45,6 +45,7 @@ import child from './meta/child.json';
import submittable from './meta/submittable.json';
import tree from './meta/tree.json';
import { Schema, SchemaStub } from './types';
import InventorySettings from './app/inventory/InventorySettings.json';
export const coreSchemas: Schema[] = [
PatchRun as Schema,
@ -99,6 +100,7 @@ export const appSchemas: Schema[] | SchemaStub[] = [
TaxDetail as Schema,
TaxSummary as Schema,
InventorySettings as Schema,
Location as Schema,
StockLedgerEntry as Schema,
StockMovement as Schema,

View File

@ -125,6 +125,11 @@ export default {
focusFirstInput: Boolean,
readOnly: { type: [null, Boolean], default: null },
},
watch: {
doc() {
this.setFormFields();
},
},
data() {
return {
inlineEditDoc: null,
@ -268,7 +273,7 @@ export default {
try {
await this.inlineEditDoc.sync();
} catch (error) {
return await handleErrorWithDialog(error, this.inlineEditDoc)
return await handleErrorWithDialog(error, this.inlineEditDoc);
}
await this.onChangeCommon(df, this.inlineEditDoc.name);

View File

@ -301,7 +301,9 @@ export default {
this.creatingDemo = false;
},
async setFiles() {
this.files = await ipcRenderer.invoke(IPC_ACTIONS.GET_DB_LIST);
this.files = (await ipcRenderer.invoke(IPC_ACTIONS.GET_DB_LIST))?.sort(
(a, b) => Date.parse(b.modified) - Date.parse(a.modified)
);
},
async newDatabase() {
if (this.creatingDemo) {

View File

@ -29,7 +29,11 @@
<!-- Component -->
<div class="flex-1 overflow-y-auto custom-scroll">
<component :is="activeTabComponent" @change="handleChange" />
<component
:is="tabs[activeTab].component"
:schema-name="tabs[activeTab].schemaName"
@change="handleChange"
/>
</div>
</template>
</FormContainer>
@ -47,11 +51,10 @@ import { docsPathMap } from 'src/utils/misc';
import { docsPath, showToast } from 'src/utils/ui';
import { IPC_MESSAGES } from 'utils/messages';
import { h, markRaw } from 'vue';
import TabDefaults from './TabDefaults.vue';
import TabBase from './TabBase.vue';
import TabGeneral from './TabGeneral.vue';
import TabInvoice from './TabInvoice.vue';
import TabSystem from './TabSystem.vue';
export default {
name: 'Settings',
components: {
@ -70,21 +73,31 @@ export default {
{
key: 'Invoice',
label: t`Invoice`,
schemaName: 'PrintSettings',
component: markRaw(TabInvoice),
},
{
key: 'General',
label: t`General`,
schemaName: 'AccountingSettings',
component: markRaw(TabGeneral),
},
{
key: 'Defaults',
label: t`Defaults`,
component: markRaw(TabDefaults),
schemaName: 'Defaults',
component: markRaw(TabBase),
},
{
key: 'Inventory',
label: t`Inventory`,
schemaName: 'InventorySettings',
component: markRaw(TabBase),
},
{
key: 'System',
label: t`System`,
schemaName: 'SystemSettings',
component: markRaw(TabSystem),
},
],
@ -154,10 +167,5 @@ export default {
};
},
},
computed: {
activeTabComponent() {
return this.tabs[this.activeTab].component;
},
},
};
</script>

View File

@ -12,15 +12,39 @@
</template>
<script lang="ts">
import { Doc } from 'fyo/model/doc';
import { Field } from 'schemas/types';
import TwoColumnForm from 'src/components/TwoColumnForm.vue';
import { defineComponent } from 'vue';
export default {
export default defineComponent({
name: 'TabGeneral',
emits: ['change'],
props: { schemaName: String },
components: {
TwoColumnForm,
},
async mounted() {
await this.setDoc();
},
watch: {
async schemaName() {
await this.setDoc();
},
},
methods: {
async setDoc() {
if (this.doc && this.schemaName === this.doc.schemaName) {
return;
}
if (!this.schemaName) {
return;
}
this.doc = await this.fyo.doc.getDoc(this.schemaName, this.schemaName, {
skipDocumentCache: true,
});
},
},
data() {
return {
doc: undefined,
@ -28,8 +52,12 @@ export default {
},
computed: {
fields() {
return [] as Field[];
console.log(
'changed',
this.doc?.schema.fields.map(({ fieldname }) => fieldname).join(',')
);
return this.doc?.schema.fields;
},
},
};
});
</script>

View File

@ -1,20 +0,0 @@
<script lang="ts">
import { fyo } from 'src/initFyo';
import { defineComponent } from 'vue';
import TabBase from './TabBase.vue';
export default defineComponent({
extends: TabBase,
name: 'TabDefaults',
async mounted() {
this.doc = await fyo.doc.getDoc('Defaults', 'Defaults', {
skipDocumentCache: true,
});
},
computed: {
fields() {
return this.doc?.schema.fields;
},
},
});
</script>

View File

@ -23,7 +23,6 @@ import { ModelNameEnum } from 'models/types';
import LanguageSelector from 'src/components/Controls/LanguageSelector.vue';
import TwoColumnForm from 'src/components/TwoColumnForm';
import { fyo } from 'src/initFyo';
import { getCountryInfo } from 'utils/misc';
export default {
name: 'TabSystem',
@ -42,7 +41,6 @@ export default {
this.doc = fyo.singles.SystemSettings;
this.companyName = fyo.singles.AccountingSettings.companyName;
this.telemetry = fyo.config.get(ConfigKeys.Telemetry);
window.gci = getCountryInfo;
},
computed: {
fields() {

View File

@ -5,14 +5,23 @@ import { createNumberSeries } from 'fyo/model/naming';
import {
DEFAULT_CURRENCY,
DEFAULT_LOCALE,
DEFAULT_SERIES_START
DEFAULT_SERIES_START,
} from 'fyo/utils/consts';
import { AccountRootTypeEnum } from 'models/baseModels/Account/types';
import { ValueError } from 'fyo/utils/errors';
import {
AccountRootTypeEnum,
AccountTypeEnum,
} from 'models/baseModels/Account/types';
import { AccountingSettings } from 'models/baseModels/AccountingSettings/AccountingSettings';
import { numberSeriesDefaultsMap } from 'models/baseModels/Defaults/Defaults';
import { InventorySettings } from 'models/inventory/InventorySettings';
import { valuationMethod } from 'models/inventory/types';
import { ModelNameEnum } from 'models/types';
import { createRegionalRecords } from 'src/regional';
import { initializeInstance, setCurrencySymbols } from 'src/utils/initialization';
import {
initializeInstance,
setCurrencySymbols,
} from 'src/utils/initialization';
import { getRandomString } from 'utils';
import { defaultUOMs } from 'utils/defaults';
import { getCountryCodeFromCountry, getCountryInfo } from 'utils/misc';
@ -39,6 +48,7 @@ export default async function setupInstance(
await createRegionalRecords(country, fyo);
await createDefaultEntries(fyo);
await createDefaultNumberSeries(fyo);
await updateInventorySettings(fyo);
await completeSetup(companyName, fyo);
if (!Object.keys(fyo.currencySymbols).length) {
@ -329,3 +339,40 @@ async function createDefaultNumberSeries(fyo: Fyo) {
await fyo.singles.Defaults?.setAndSync(defaultKey as string, defaultValue);
}
}
async function updateInventorySettings(fyo: Fyo) {
const inventorySettings = (await fyo.doc.getDoc(
ModelNameEnum.InventorySettings
)) as InventorySettings;
if (!inventorySettings.valuationMethod) {
await inventorySettings.set('valuationMethod', valuationMethod.FIFO);
}
const stockAccounts = (await fyo.db.getAllRaw('Account', {
filters: { accountType: AccountTypeEnum.Stock, isGroup: false },
})) as { name: string }[];
if (stockAccounts.length && !inventorySettings.stockInHand) {
await inventorySettings.set('stockInHand', stockAccounts[0].name);
}
const stockReceivedButNotBilled = (await fyo.db.getAllRaw('Account', {
filters: {
accountType: AccountTypeEnum['Stock Received But Not Billed'],
isGroup: false,
},
})) as { name: string }[];
if (
stockReceivedButNotBilled.length &&
!inventorySettings.stockInReceivedButNotBilled
) {
await inventorySettings.set(
'stockInReceivedButNotBilled',
stockAccounts[0].name
);
}
await inventorySettings.sync();
}

View File

@ -44,10 +44,13 @@ async function closeDbIfConnected(fyo: Fyo) {
}
async function setSingles(fyo: Fyo) {
await fyo.doc.getDoc(ModelNameEnum.AccountingSettings);
await fyo.doc.getDoc(ModelNameEnum.GetStarted);
await fyo.doc.getDoc(ModelNameEnum.Defaults);
await fyo.doc.getDoc(ModelNameEnum.Misc);
for (const schema of Object.values(fyo.schemaMap)) {
if (!schema?.isSingle || schema.name === ModelNameEnum.SetupWizard) {
continue;
}
await fyo.doc.getDoc(schema.name);
}
}
async function setCreds(fyo: Fyo) {