2
0
mirror of https://github.com/frappe/books.git synced 2024-11-14 01:14:03 +00:00

incr: use Stock Manager in Stock Queue

This commit is contained in:
18alantom 2022-10-29 11:45:23 +05:30
parent daaf56da48
commit d9f47c01e3
4 changed files with 135 additions and 32 deletions

View File

@ -4,6 +4,7 @@ import { ModelNameEnum } from 'models/types';
import { Money } from 'pesa'; import { Money } from 'pesa';
import { getStockQueue } from './helpers'; import { getStockQueue } from './helpers';
import { StockLedgerEntry } from './StockLedgerEntry'; import { StockLedgerEntry } from './StockLedgerEntry';
import { StockQueue } from './StockQueue';
import { SMDetails } from './types'; import { SMDetails } from './types';
export class StockManager { export class StockManager {
@ -20,63 +21,96 @@ export class StockManager {
* 7. Insert Stock Ledger Entry * 7. Insert Stock Ledger Entry
*/ */
date?: Date; date: Date;
item?: string; item: string;
rate?: Money; rate: Money;
quantity?: number; quantity: number;
referenceName: string;
referenceType: string;
fromLocation?: string; fromLocation?: string;
toLocation?: string; toLocation?: string;
referenceName?: string;
referenceType?: string; stockQueues?: StockQueue[];
stockValue?: string; stockLedgerEntries?: StockLedgerEntry[];
stockValueDifference?: string;
fyo: Fyo; fyo: Fyo;
constructor(fyo: Fyo) { constructor(details: SMDetails, fyo: Fyo) {
this.fyo = fyo;
}
moveStock(details: SMDetails) {
this.date = details.date; this.date = details.date;
this.item = details.item; this.item = details.item;
this.rate = details.rate;
this.quantity = details.quantity; this.quantity = details.quantity;
this.fromLocation = details.fromLocation; this.fromLocation = details.fromLocation;
this.toLocation = details.toLocation; this.toLocation = details.toLocation;
this.referenceName = details.referenceName; this.referenceName = details.referenceName;
this.referenceType = details.referenceType; this.referenceType = details.referenceType;
this.#validate(); this.#validate();
this.#moveStockForBothLocations();
this.fyo = fyo;
} }
async #moveStockForBothLocations() { async transferStock(isCancelled: boolean) {
this.#clear();
await this.#moveStockForBothLocations(isCancelled);
}
async sync() {
for (const sq of this.stockQueues ?? []) {
await sq.sync();
}
for (const sle of this.stockLedgerEntries ?? []) {
await sle.sync();
}
}
async #moveStockForBothLocations(isCancelled: boolean) {
if (this.fromLocation) { if (this.fromLocation) {
await this.#moveStockForSingleLocation(this.fromLocation, true); await this.#moveStockForSingleLocation(
this.fromLocation,
isCancelled ? false : true,
isCancelled
);
} }
if (this.toLocation) { if (this.toLocation) {
await this.#moveStockForSingleLocation(this.toLocation, false); await this.#moveStockForSingleLocation(
this.toLocation,
isCancelled ? true : false,
isCancelled
);
} }
} }
async #moveStockForSingleLocation(location: string, isOutward: boolean) { async #moveStockForSingleLocation(
location: string,
isOutward: boolean,
isCancelled: boolean
) {
let quantity = this.quantity!; let quantity = this.quantity!;
if (quantity === 0) {
return;
}
if (isOutward) { if (isOutward) {
quantity = -quantity; quantity = -quantity;
} }
// Stock Queue Changes
const { stockQueue, stockValueBefore, stockValueAfter } = const { stockQueue, stockValueBefore, stockValueAfter } =
await this.#makeStockQueueChange(location, isOutward); await this.#makeStockQueueChange(location, isOutward);
const stockLedgerEntry = this.#getStockLedgerEntry( this.stockQueues?.push(stockQueue);
location,
quantity,
stockValueBefore,
stockValueAfter
);
await stockQueue.sync(); // Stock Ledger Entry
await stockLedgerEntry.sync(); if (!isCancelled) {
const stockLedgerEntry = this.#getStockLedgerEntry(
location,
quantity,
stockValueBefore,
stockValueAfter
);
this.stockLedgerEntries?.push(stockLedgerEntry);
}
} }
#getStockLedgerEntry( #getStockLedgerEntry(
@ -123,11 +157,29 @@ export class StockManager {
return { stockQueue, stockValueBefore, stockValueAfter }; return { stockQueue, stockValueBefore, stockValueAfter };
} }
#clear() {
this.stockQueues = [];
this.stockLedgerEntries = [];
}
#validate() { #validate() {
this.#validateRate(); this.#validateRate();
this.#validateQuantity();
this.#validateLocation(); this.#validateLocation();
} }
#validateQuantity() {
if (!this.quantity) {
throw new ValidationError(t`Stock Manager: quantity needs to be set`);
}
if (this.quantity <= 0) {
throw new ValidationError(
t`Stock Manager: quantity (${this.quantity}) has to be greater than zero`
);
}
}
#validateRate() { #validateRate() {
if (!this.rate) { if (!this.rate) {
throw new ValidationError(t`Stock Manager: rate needs to be set`); throw new ValidationError(t`Stock Manager: rate needs to be set`);

View File

@ -7,6 +7,7 @@ import {
} from 'fyo/model/types'; } from 'fyo/model/types';
import { ModelNameEnum } from 'models/types'; import { ModelNameEnum } from 'models/types';
import { Money } from 'pesa'; import { Money } from 'pesa';
import { StockManager } from './StockManager';
import { StockMovementItem } from './StockMovementItem'; import { StockMovementItem } from './StockMovementItem';
import { MovementType } from './types'; import { MovementType } from './types';
@ -41,4 +42,49 @@ export class StockMovement extends Doc {
static getListViewSettings(): ListViewSettings { static getListViewSettings(): ListViewSettings {
return { columns: ['name', 'date', 'movementType'] }; return { columns: ['name', 'date', 'movementType'] };
} }
async afterSubmit(): Promise<void> {
await this._transferStock();
}
async afterCancel(): Promise<void> {
await this._transferStock();
}
async _transferStock() {
const stockManagers = this._getStockManagers();
for (const sm of stockManagers) {
sm.transferStock(this.isCancelled);
}
for (const sm of stockManagers) {
await sm.sync();
}
}
_getStockManagers(): StockManager[] {
const stockManagers: StockManager[] = [];
for (const row of this.items ?? []) {
const stockManager = this._getStockManager(row);
stockManagers.push(stockManager);
}
return stockManagers;
}
_getStockManager(row: StockMovementItem): StockManager {
return new StockManager(
{
date: this.date!,
item: row.item!,
rate: row.rate!,
quantity: row.quantity!,
referenceName: this.name!,
referenceType: this.schemaName,
fromLocation: row.fromLocation,
toLocation: row.toLocation,
},
this.fyo
);
}
} }

View File

@ -1,7 +1,6 @@
import { Doc } from 'fyo/model/doc'; import { Doc } from 'fyo/model/doc';
import { Money } from 'pesa'; import { Money } from 'pesa';
import { StockQueueItem } from './types';
type StockQueueItem = { rate: Money; quantity: number };
export class StockQueue extends Doc { export class StockQueue extends Doc {
item?: string; item?: string;
@ -12,8 +11,12 @@ export class StockQueue extends Doc {
/** /**
* Stock Queue * Stock Queue
* *
* Used to keep track of inward rates for * Used to keep track of inward rates for stock
* stock valuation purposes. * valuation purposes.
*
* Stock Queue uses autoincrement as PK as opposed
* to (item, location, ...) to prevent NULL value
* primary keys.
*/ */
get quantity(): number { get quantity(): number {

View File

@ -15,3 +15,5 @@ export interface SMDetails {
fromLocation?: string; fromLocation?: string;
toLocation?: string; toLocation?: string;
} }
export type StockQueueItem = { rate: Money; quantity: number };