2
0
mirror of https://github.com/frappe/books.git synced 2024-09-18 18:49:01 +00:00

incr: add enable inventory

- add basic inventory schemas
- add basic inventory models
- patch stockmovement number series
This commit is contained in:
18alantom 2022-10-05 20:07:17 +05:30
parent afcc5fb2b2
commit 2c0540bfd5
24 changed files with 469 additions and 13 deletions

View File

@ -0,0 +1,22 @@
import { getDefaultMetaFieldValueMap } from '../../backend/helpers';
import { DatabaseManager } from '../database/manager';
async function execute(dm: DatabaseManager) {
const schemaName = 'NumberSeries';
const name = 'SMOV-';
const exists = await dm.db?.exists(schemaName, name);
if (exists) {
return;
}
await dm.db?.insert(schemaName, {
name,
start: 1001,
padZeros: 4,
current: 0,
referenceType: 'StockMovement',
...getDefaultMetaFieldValueMap(),
});
}
export default { execute, beforeMigrate: true };

View File

@ -1,5 +1,6 @@
import { Patch } from '../database/types';
import addUOMs from './addUOMs';
import createInventoryNumberSeries from './createInventoryNumberSeries';
import fixRoundOffAccount from './fixRoundOffAccount';
import testPatch from './testPatch';
import updateSchemas from './updateSchemas';
@ -20,6 +21,11 @@ export default [
{
name: 'fixRoundOffAccount',
version: '0.6.3-beta.0',
patch: fixRoundOffAccount
patch: fixRoundOffAccount,
},
{
name: 'createInventoryNumberSeries',
version: '0.6.6-beta.0',
patch: createInventoryNumberSeries,
},
] as Patch[];

View File

@ -9,7 +9,7 @@ import {
DEFAULT_CURRENCY,
DEFAULT_DATE_FORMAT,
DEFAULT_DISPLAY_PRECISION,
DEFAULT_LOCALE,
DEFAULT_LOCALE
} from './consts';
export function format(
@ -32,6 +32,10 @@ export function format(
return formatDate(value, fyo);
}
if (field.fieldtype === FieldTypeEnum.Datetime) {
return formatDate(value, fyo);
}
if (field.fieldtype === FieldTypeEnum.Check) {
return Boolean(value).toString();
}

View File

@ -5,14 +5,17 @@ import {
Action,
FiltersMap,
FormulaMap,
HiddenMap,
ListViewSettings,
ValidationMap,
ValidationMap
} from 'fyo/model/types';
import { ValidationError } from 'fyo/utils/errors';
import { Money } from 'pesa';
import { AccountRootTypeEnum, AccountTypeEnum } from '../Account/types';
export class Item extends Doc {
itemType?: 'Product' | 'Service';
formulas: FormulaMap = {
incomeAccount: {
formula: async () => {
@ -99,4 +102,8 @@ export class Item extends Doc {
columns: ['name', 'unit', 'tax', 'rate'],
};
}
hidden: HiddenMap = {
trackItem: () => this.itemType !== 'Product',
};
}

View File

@ -17,6 +17,11 @@ 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 { Location } from './inventory/Location';
import { StockLedgerEntry } from './inventory/StockLedgerEntry';
import { StockMovement } from './inventory/StockMovement';
import { StockMovementItem } from './inventory/StockMovementItem';
import { StockQueue } from './inventory/StockQueue';
export const models = {
Account,
@ -37,6 +42,12 @@ export const models = {
SetupWizard,
Tax,
TaxSummary,
// Inventory Models
StockQueue,
StockMovement,
StockMovementItem,
StockLedgerEntry,
Location,
} as ModelMap;
export async function getRegionalModels(

View File

@ -0,0 +1,5 @@
import { Doc } from 'fyo/model/doc';
export class Location extends Doc {
item?: string;
}

View File

@ -0,0 +1,3 @@
import { Doc } from 'fyo/model/doc';
export class StockLedgerEntry extends Doc {}

View File

@ -0,0 +1,27 @@
import { Doc } from 'fyo/model/doc';
import { DefaultMap, FiltersMap, ListViewSettings } from 'fyo/model/types';
import { ModelNameEnum } from 'models/types';
import { Money } from 'pesa';
import { StockMovementItem } from './StockMovementItem';
import { MovementType } from './types';
export class StockMovement extends Doc {
name?: string;
date?: Date;
numberSeries?: string;
movementType?: MovementType;
items?: StockMovementItem;
amount?: Money;
static filters: FiltersMap = {
numberSeries: () => ({ referenceType: ModelNameEnum.StockMovement }),
};
static defaults: DefaultMap = {
date: () => new Date(),
};
static getListViewSettings(): ListViewSettings {
return { columns: ['name', 'date', 'movementType'] };
}
}

View File

@ -0,0 +1,29 @@
import { Doc } from 'fyo/model/doc';
import { FilterFunction, FiltersMap } from 'fyo/model/types';
import { Money } from 'pesa';
import { QueryFilter } from 'utils/db/types';
const locationFilter: FilterFunction = (doc: Doc) => {
const item = doc.item;
if (!doc.item) {
return {};
}
return { item } as QueryFilter;
};
export class StockMovementItem extends Doc {
name?: string;
item?: string;
fromLocation?: string;
toLocation?: string;
quantity?: number;
rate?: Money;
amount?: Money;
static filters: FiltersMap = {
item: () => ({ trackItem: true }),
toLocation: locationFilter,
fromLocation: locationFilter,
};
}

View File

@ -0,0 +1,3 @@
import { Doc } from 'fyo/model/doc';
export class StockQueue extends Doc {}

View File

@ -0,0 +1,4 @@
export type MovementType =
| 'MaterialIssue'
| 'MaterialReceipt'
| 'MaterialTransfer';

View File

@ -30,6 +30,11 @@ export enum ModelNameEnum {
PatchRun = 'PatchRun',
SingleValue = 'SingleValue',
SystemSettings = 'SystemSettings',
StockMovement = 'StockMovement',
StockQueue = 'StockQueue',
StockMovementItem = 'StockMovementItem',
StockLedgerEntry = 'StockLedgerEntry',
Location = 'Location',
}
export type ModelName = keyof typeof ModelNameEnum;

View File

@ -105,6 +105,12 @@
"label": "HSN/SAC",
"fieldtype": "Int",
"placeholder": "HSN/SAC Code"
},
{
"fieldname": "trackItem",
"label": "Track Item",
"fieldtype": "Check",
"default": false
}
],
"quickEditFields": [
@ -116,7 +122,8 @@
"description",
"incomeAccount",
"expenseAccount",
"hsnCode"
"hsnCode",
"trackItem"
],
"keywordFields": ["name", "itemType", "for"]
}

View File

@ -46,6 +46,10 @@
{
"value": "JournalEntry",
"label": "Journal Entry"
},
{
"value": "StockMovement",
"label": "Stock Movement"
}
],
"default": "-",

View File

@ -0,0 +1,25 @@
{
"name": "Location",
"label": "Location",
"isSingle": false,
"isChild": false,
"naming": "manual",
"fields": [
{
"fieldname": "name",
"label": "Location Name",
"fieldtype": "Data",
"required": true
},
{
"fieldname": "item",
"label": "Item",
"fieldtype": "Link",
"target": "Item",
"required": true
}
],
"quickEditFields": [
"item"
]
}

View File

@ -0,0 +1,86 @@
{
"name": "StockLedgerEntry",
"label": "Stock Ledger Entry",
"isSingle": false,
"isChild": false,
"naming": "autoincrement",
"fields": [
{
"fieldname": "date",
"label": "Date",
"fieldtype": "Datetime",
"readOnly": true
},
{
"fieldname": "item",
"label": "Item",
"fieldtype": "Link",
"target": "Item",
"readOnly": true
},
{
"fieldname": "rate",
"label": "Rate",
"fieldtype": "Currency",
"readOnly": true
},
{
"fieldname": "quantity",
"label": "Quantity",
"fieldtype": "Float",
"readOnly": true
},
{
"fieldname": "fromLocation",
"label": "From Location",
"fieldtype": "Link",
"target": "Location",
"readOnly": true
},
{
"fieldname": "toLocation",
"label": "To Location",
"fieldtype": "Link",
"target": "Location",
"readOnly": true
},
{
"fieldname": "referenceDetailName",
"label": "Ref. Detail Name",
"fieldtype": "DynamicLink",
"references": "referenceDetailType",
"readOnly": true
},
{
"fieldname": "referenceDetailType",
"label": "Ref. Detail Type",
"fieldtype": "Data",
"readOnly": true
},
{
"fieldname": "referenceName",
"label": "Ref. Name",
"fieldtype": "DynamicLink",
"references": "referenceType",
"readOnly": true
},
{
"fieldname": "referenceType",
"label": "Ref. Type",
"fieldtype": "Data",
"readOnly": true
},
{
"fieldname": "stockValue",
"label": "Stock Value",
"fieldtype": "Currency",
"readOnly": true
},
{
"fieldname": "stockValueDifference",
"label": "Stock Value Difference",
"fieldtype": "Currency",
"readOnly": true
}
]
}

View File

@ -0,0 +1,73 @@
{
"name": "StockMovement",
"label": "Stock Movement",
"naming": "numberSeries",
"isSingle": false,
"isChild": false,
"isSubmittable": true,
"fields": [
{
"label": "Stock Movement No.",
"fieldname": "name",
"fieldtype": "Data",
"required": true,
"readOnly": true
},
{
"fieldname": "date",
"label": "Posting Date",
"fieldtype": "Datetime",
"required": true
},
{
"fieldname": "movementType",
"label": "Movement Type",
"fieldtype": "Select",
"options": [
{
"value": "MaterialIssue",
"label": "Material Issue"
},
{
"value": "MaterialReceipt",
"label": "Material Receipt"
},
{
"value": "MaterialTransfer",
"label": "Material Transfer"
}
],
"required": true
},
{
"fieldname": "numberSeries",
"label": "Number Series",
"fieldtype": "Link",
"target": "NumberSeries",
"create": true,
"required": true,
"default": "SMOV-"
},
{
"fieldname": "amount",
"label": "Amount",
"fieldtype": "Currency",
"readOnly": true
},
{
"fieldname": "items",
"label": "Items",
"fieldtype": "Table",
"target": "StockMovementItem",
"required": true
}
],
"quickEditFields": [
"numberSeries",
"date",
"movementType",
"amount",
"items"
],
"keywordFields": ["name", "movementType"]
}

View File

@ -0,0 +1,59 @@
{
"name": "StockMovementItem",
"label": "Stock Movement Item",
"naming": "random",
"isChild": true,
"fields": [
{
"fieldname": "item",
"label": "Item",
"fieldtype": "Link",
"target": "Item",
"create": true,
"required": true
},
{
"fieldname": "fromLocation",
"label": "From",
"fieldtype": "Link",
"target": "Location",
"create": true
},
{
"fieldname": "toLocation",
"label": "To",
"fieldtype": "Link",
"target": "Location",
"create": true
},
{
"fieldname": "quantity",
"label": "Quantity",
"fieldtype": "Float",
"required": true,
"default": 1
},
{
"fieldname": "rate",
"label": "Rate",
"fieldtype": "Currency",
"required": true
},
{
"fieldname": "amount",
"label": "Amount",
"fieldtype": "Currency",
"readOnly": true
}
],
"tableFields": ["item", "fromLocation", "toLocation", "quantity", "rate"],
"keywordFields": ["item"],
"quickEditFields": [
"item",
"fromLocation",
"toLocation",
"quantity",
"rate",
"amount"
]
}

View File

@ -0,0 +1,41 @@
{
"name": "StockQueue",
"label": "Stock Queue",
"isSingle": false,
"isChild": false,
"naming": "random",
"fields": [
{
"fieldname": "item",
"label": "Item",
"fieldtype": "Link",
"target": "Item",
"readOnly": true
},
{
"fieldname": "location",
"label": "Location",
"fieldtype": "Link",
"target": "Location",
"readOnly": true
},
{
"fieldname": "queue",
"label": "Queue",
"fieldtype": "Data",
"readOnly": true
},
{
"fieldname": "stockValue",
"label": "Stock Value",
"fieldtype": "Currency",
"readOnly": true
},
{
"fieldname": "valuationRate",
"label": "Valuation Rate",
"fieldtype": "Currency",
"readOnly": true
}
]
}

View File

@ -7,6 +7,11 @@ import CompanySettings from './app/CompanySettings.json';
import Currency from './app/Currency.json';
import Defaults from './app/Defaults.json';
import GetStarted from './app/GetStarted.json';
import Location from './app/inventory/Location.json';
import StockLedgerEntry from './app/inventory/StockLedgerEntry.json';
import StockMovement from './app/inventory/StockMovement.json';
import StockMovementItem from './app/inventory/StockMovementItem.json';
import StockQueue from './app/inventory/StockQueue.json';
import Invoice from './app/Invoice.json';
import InvoiceItem from './app/InvoiceItem.json';
import Item from './app/Item.json';
@ -88,4 +93,10 @@ export const appSchemas: Schema[] | SchemaStub[] = [
Tax as Schema,
TaxDetail as Schema,
TaxSummary as Schema,
Location as Schema,
StockQueue as Schema,
StockLedgerEntry as Schema,
StockMovement as Schema,
StockMovementItem as Schema,
];

View File

@ -24,6 +24,7 @@ const components = {
Select,
Link,
Date,
Datetime: Date,
Table,
AutoComplete,
DynamicLink,

View File

@ -185,6 +185,7 @@ export default {
},
tableFields() {
const fields = fyo.schemaMap[this.df.target].tableFields ?? [];
console.log(this.df, fields);
return fields.map((fieldname) => fyo.getField(this.df.target, fieldname));
},
},

View File

@ -167,7 +167,7 @@ export default {
async mounted() {
const { companyName } = await fyo.doc.getDoc('AccountingSettings');
this.companyName = companyName;
this.groups = getSidebarConfig();
this.groups = await getSidebarConfig();
this.setActiveGroup();
router.afterEach(() => {

View File

@ -1,12 +1,21 @@
import { t } from 'fyo';
import { Fyo, t } from 'fyo';
import { fyo } from '../initFyo';
import { SidebarConfig, SidebarRoot } from './types';
export function getSidebarConfig(): SidebarConfig {
const sideBar = getCompleteSidebar();
export async function getSidebarConfig(): Promise<SidebarConfig> {
const sideBar = await getCompleteSidebar();
return getFilteredSidebar(sideBar);
}
async function getIsInventoryEnabled(fyo: Fyo) {
const values = await fyo.db.getAllRaw('Item', {
fields: ['name'],
filters: { trackItem: true },
});
return !!values.length;
}
function getFilteredSidebar(sideBar: SidebarConfig): SidebarConfig {
return sideBar.filter((root) => {
root.items = root.items?.filter((item) => {
@ -53,19 +62,32 @@ function getRegionalSidebar(): SidebarRoot[] {
];
}
function getInventorySidebar(): SidebarRoot[] {
async function getInventorySidebar(): Promise<SidebarRoot[]> {
const showInventory = await getIsInventoryEnabled(fyo);
if (!showInventory) {
return [];
}
return [
{
label: t`Inventory`,
name: 'inventory',
icon: 'inventory',
iconSize: '18',
route: '/',
route: '/list/StockMovement',
items: [
{
label: t`Stock Movement`,
name: 'stock-movement',
route: '/list/StockMovement',
schemaName: 'StockMovement',
},
],
},
];
}
function getCompleteSidebar(): SidebarConfig {
async function getCompleteSidebar(): Promise<SidebarConfig> {
return [
{
label: t`Get Started`,
@ -200,8 +222,8 @@ function getCompleteSidebar(): SidebarConfig {
},
],
},
getInventorySidebar(),
getRegionalSidebar(),
await getInventorySidebar(),
await getRegionalSidebar(),
{
label: t`Setup`,
name: 'setup',