From d394db817ed8afd9592d27317d7b24029acfa57a Mon Sep 17 00:00:00 2001 From: 18alantom <2.alan.tom@gmail.com> Date: Tue, 1 Nov 2022 13:57:02 +0530 Subject: [PATCH] incr: stateless stock-ledger, remove stock queue --- models/index.ts | 2 - models/inventory/StockLedgerEntry.ts | 2 - models/inventory/StockManager.ts | 58 +--------- models/inventory/StockQueue.ts | 122 -------------------- models/inventory/helpers.ts | 28 ----- models/inventory/types.ts | 1 - models/types.ts | 1 - schemas/app/inventory/StockLedgerEntry.json | 12 -- schemas/app/inventory/StockQueue.json | 38 ------ schemas/schemas.ts | 2 - 10 files changed, 2 insertions(+), 264 deletions(-) delete mode 100644 models/inventory/StockQueue.ts delete mode 100644 schemas/app/inventory/StockQueue.json diff --git a/models/index.ts b/models/index.ts index 6d9a3f79..937a4d34 100644 --- a/models/index.ts +++ b/models/index.ts @@ -21,7 +21,6 @@ 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, @@ -43,7 +42,6 @@ export const models = { Tax, TaxSummary, // Inventory Models - StockQueue, StockMovement, StockMovementItem, StockLedgerEntry, diff --git a/models/inventory/StockLedgerEntry.ts b/models/inventory/StockLedgerEntry.ts index 708011a0..d137bfea 100644 --- a/models/inventory/StockLedgerEntry.ts +++ b/models/inventory/StockLedgerEntry.ts @@ -10,6 +10,4 @@ export class StockLedgerEntry extends Doc { location?: string; referenceName?: string; referenceType?: string; - stockValueBefore?: Money; - stockValueAfter?: Money; } diff --git a/models/inventory/StockManager.ts b/models/inventory/StockManager.ts index 739fa078..406b7fb7 100644 --- a/models/inventory/StockManager.ts +++ b/models/inventory/StockManager.ts @@ -2,9 +2,7 @@ import { Fyo, t } from 'fyo'; import { ValidationError } from 'fyo/utils/errors'; import { ModelNameEnum } from 'models/types'; import { Money } from 'pesa'; -import { getStockQueue } from './helpers'; import { StockLedgerEntry } from './StockLedgerEntry'; -import { StockQueue } from './StockQueue'; import { SMDetails, SMIDetails, SMTransferDetails } from './types'; export class StockManager { @@ -51,11 +49,7 @@ export class StockManagerItem { * updates the Stock Queue and creates Stock Ledger Entries. * * 1. Get existing stock Queue - * 2. Get Stock Value Before from Stock Queue - * 3. Update Stock Queue - * 4. Get Stock Value After from Stock Queue * 5. Create Stock Ledger Entry - * 6. Save Stock Queue * 7. Insert Stock Ledger Entry */ @@ -68,7 +62,6 @@ export class StockManagerItem { fromLocation?: string; toLocation?: string; - stockQueues?: StockQueue[]; stockLedgerEntries?: StockLedgerEntry[]; fyo: Fyo; @@ -93,10 +86,6 @@ export class StockManagerItem { } async sync() { - for (const sq of this.stockQueues ?? []) { - await sq.sync(); - } - for (const sle of this.stockLedgerEntries ?? []) { await sle.sync(); } @@ -134,69 +123,26 @@ export class StockManagerItem { quantity = -quantity; } - // Stock Queue Changes - const { stockQueue, stockValueBefore, stockValueAfter } = - await this.#makeStockQueueChange(location, isOutward); - this.stockQueues?.push(stockQueue); - // Stock Ledger Entry if (!isCancelled) { - const stockLedgerEntry = this.#getStockLedgerEntry( - location, - quantity, - stockValueBefore, - stockValueAfter - ); + const stockLedgerEntry = this.#getStockLedgerEntry(location, quantity); this.stockLedgerEntries?.push(stockLedgerEntry); } } - #getStockLedgerEntry( - location: string, - quantity: number, - stockValueBefore: Money, - stockValueAfter: Money - ) { + #getStockLedgerEntry(location: string, quantity: number) { return this.fyo.doc.getNewDoc(ModelNameEnum.StockLedgerEntry, { date: this.date, item: this.item, rate: this.rate, quantity, location, - stockValueBefore, - stockValueAfter, referenceName: this.referenceName, referenceType: this.referenceType, }) as StockLedgerEntry; } - async #makeStockQueueChange(location: string, isOutward: boolean) { - const stockQueue = await getStockQueue(this.item!, location, this.fyo); - const stockValueBefore = stockQueue.stockValue!; - let isSuccess; - - if (isOutward) { - isSuccess = stockQueue.outward(-this.quantity!); - } else { - isSuccess = stockQueue.inward(this.rate!, this.quantity!); - } - - if (!isSuccess && isOutward) { - throw new ValidationError( - t`Stock Manager: Insufficient quantity ${ - stockQueue.quantity - } at ${location} of ${this - .item!} for outward transaction. Quantity required ${this.quantity!}.` - ); - } - - const stockValueAfter = stockQueue.stockValue!; - - return { stockQueue, stockValueBefore, stockValueAfter }; - } - #clear() { - this.stockQueues = []; this.stockLedgerEntries = []; } diff --git a/models/inventory/StockQueue.ts b/models/inventory/StockQueue.ts deleted file mode 100644 index f7954752..00000000 --- a/models/inventory/StockQueue.ts +++ /dev/null @@ -1,122 +0,0 @@ -import { Doc } from 'fyo/model/doc'; -import { Money } from 'pesa'; -import { StockQueueItem } from './types'; - -export class StockQueue extends Doc { - item?: string; - location?: string; - queue?: string; - stockValue?: Money; - - /** - * Stock Queue - * - * Used to keep track of inward rates for stock - * valuation purposes. - * - * Stock Queue uses autoincrement as PK as opposed - * to (item, location, ...) to prevent NULL value - * primary keys. - */ - - get quantity(): number { - return this.stockQueue.reduce((qty, sqi) => { - return qty + sqi.quantity; - }, 0); - } - - get stockQueue(): StockQueueItem[] { - const stringifiedRatesQueue = JSON.parse(this.queue ?? '[]') as { - rate: string; - quantity: number; - }[]; - - return stringifiedRatesQueue.map(({ rate, quantity }) => ({ - rate: this.fyo.pesa(rate), - quantity, - })); - } - - set stockQueue(stockQueue: StockQueueItem[]) { - const stringifiedRatesQueue = stockQueue.map(({ rate, quantity }) => ({ - rate: rate.store, - quantity, - })); - this.queue = JSON.stringify(stringifiedRatesQueue); - } - - inward(rate: Money, quantity: number): boolean { - const stockQueue = this.stockQueue; - stockQueue.push({ rate, quantity }); - this.stockQueue = stockQueue; - - this._updateStockValue(stockQueue); - return true; - } - - outward(quantity: number): boolean { - const stockQueue = this.stockQueue; - const outwardQueues = getQueuesPostOutwards(stockQueue, quantity); - if (!outwardQueues.isPossible) { - return false; - } - - this.stockQueue = outwardQueues.balanceQueue; - this._updateStockValue(outwardQueues.balanceQueue); - return true; - } - - _updateStockValue(stockQueue: StockQueueItem[]) { - this.stockValue = stockQueue.reduce((acc, { rate, quantity }) => { - return acc.add(rate.mul(quantity)); - }, this.fyo.pesa(0)); - } -} - -function getQueuesPostOutwards( - stockQueue: StockQueueItem[], - outwardQuantity: number -) { - const totalQuantity = stockQueue.reduce( - (acc, { quantity }) => acc + quantity, - 0 - ); - - const isPossible = outwardQuantity <= totalQuantity; - if (!isPossible) { - return { isPossible }; - } - - let outwardRemaining = outwardQuantity; - const balanceQueue: StockQueueItem[] = []; - const outwardQueue: StockQueueItem[] = []; - - for (let i = stockQueue.length - 1; i >= 0; i--) { - const { quantity, rate } = stockQueue[i]; - if (outwardRemaining === 0) { - balanceQueue.unshift({ quantity, rate }); - } - - const balanceRemaining = quantity - outwardRemaining; - if (balanceRemaining === 0) { - outwardQueue.push({ quantity, rate }); - outwardRemaining = 0; - continue; - } - - if (balanceRemaining > 0) { - outwardQueue.push({ quantity: outwardRemaining, rate }); - balanceQueue.unshift({ quantity: balanceRemaining, rate }); - outwardRemaining = 0; - continue; - } - - if (balanceRemaining < 0) { - outwardQueue.push({ quantity, rate }); - outwardRemaining = +balanceRemaining; - continue; - } - } - - return { isPossible, outwardQueue, balanceQueue }; -} diff --git a/models/inventory/helpers.ts b/models/inventory/helpers.ts index d2017577..8b137891 100644 --- a/models/inventory/helpers.ts +++ b/models/inventory/helpers.ts @@ -1,29 +1 @@ -import { Fyo } from 'fyo'; -import { ModelNameEnum } from 'models/types'; -import { StockQueue } from './StockQueue'; -export async function getStockQueue( - item: string, - location: string, - fyo: Fyo -): Promise { - /** - * Create a new StockQueue if it doesn't exist. - */ - - const names = (await fyo.db.getAllRaw(ModelNameEnum.StockQueue, { - filters: { item, location }, - fields: ['name'], - limit: 1, - })) as { name: string }[]; - const name = names?.[0]?.name; - - if (!name) { - return fyo.doc.getNewDoc(ModelNameEnum.StockQueue, { - item, - location, - }) as StockQueue; - } - - return (await fyo.doc.getDoc(ModelNameEnum.StockQueue, name)) as StockQueue; -} diff --git a/models/inventory/types.ts b/models/inventory/types.ts index 30be4908..fee0a028 100644 --- a/models/inventory/types.ts +++ b/models/inventory/types.ts @@ -22,4 +22,3 @@ export interface SMTransferDetails { export interface SMIDetails extends SMDetails, SMTransferDetails {} -export type StockQueueItem = { rate: Money; quantity: number }; diff --git a/models/types.ts b/models/types.ts index a8fb4c1c..e5800e5f 100644 --- a/models/types.ts +++ b/models/types.ts @@ -31,7 +31,6 @@ export enum ModelNameEnum { SingleValue = 'SingleValue', SystemSettings = 'SystemSettings', StockMovement = 'StockMovement', - StockQueue = 'StockQueue', StockMovementItem = 'StockMovementItem', StockLedgerEntry = 'StockLedgerEntry', Location = 'Location', diff --git a/schemas/app/inventory/StockLedgerEntry.json b/schemas/app/inventory/StockLedgerEntry.json index 8874d2fc..f4955c1c 100644 --- a/schemas/app/inventory/StockLedgerEntry.json +++ b/schemas/app/inventory/StockLedgerEntry.json @@ -49,18 +49,6 @@ "label": "Ref. Type", "fieldtype": "Data", "readOnly": true - }, - { - "fieldname": "stockValueBefore", - "label": "Stock Value Before", - "fieldtype": "Currency", - "readOnly": true - }, - { - "fieldname": "stockValueAfter", - "label": "Stock Value After", - "fieldtype": "Currency", - "readOnly": true } ] } diff --git a/schemas/app/inventory/StockQueue.json b/schemas/app/inventory/StockQueue.json deleted file mode 100644 index 2888782c..00000000 --- a/schemas/app/inventory/StockQueue.json +++ /dev/null @@ -1,38 +0,0 @@ -{ - "name": "StockQueue", - "label": "Stock Queue", - "isSingle": false, - "isChild": false, - "naming": "autoincrement", - "fields": [ - { - "fieldname": "item", - "label": "Item", - "fieldtype": "Link", - "target": "Item", - "required": true, - "readOnly": true - }, - { - "fieldname": "location", - "label": "Location", - "fieldtype": "Link", - "target": "Location", - "required": true, - "readOnly": true - }, - { - "fieldname": "queue", - "label": "Queue", - "fieldtype": "Data", - "required": true, - "readOnly": true - }, - { - "fieldname": "stockValue", - "label": "Stock Value", - "fieldtype": "Currency", - "readOnly": true - } - ] -} diff --git a/schemas/schemas.ts b/schemas/schemas.ts index 40169006..654758bc 100644 --- a/schemas/schemas.ts +++ b/schemas/schemas.ts @@ -11,7 +11,6 @@ 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'; @@ -95,7 +94,6 @@ export const appSchemas: Schema[] | SchemaStub[] = [ TaxSummary as Schema, Location as Schema, - StockQueue as Schema, StockLedgerEntry as Schema, StockMovement as Schema, StockMovementItem as Schema,