diff --git a/fyo/model/types.ts b/fyo/model/types.ts index 47563666..8c2f5279 100644 --- a/fyo/model/types.ts +++ b/fyo/model/types.ts @@ -1,10 +1,14 @@ import { Fyo } from 'fyo'; import { DocValue, DocValueMap } from 'fyo/core/types'; -import SystemSettings from 'fyo/models/SystemSettings'; +import type SystemSettings from 'fyo/models/SystemSettings'; import { FieldType, Schema, SelectOption } from 'schemas/types'; import { QueryFilter } from 'utils/db/types'; import { RouteLocationRaw, Router } from 'vue-router'; import { Doc } from './doc'; +import type { AccountingSettings } from 'models/baseModels/AccountingSettings/AccountingSettings'; +import type { Defaults } from 'models/baseModels/Defaults/Defaults'; +import type { PrintSettings } from 'models/baseModels/PrintSettings/PrintSettings'; +import type { InventorySettings } from 'models/inventory/InventorySettings'; /** * The functions below are used for dynamic evaluation @@ -47,6 +51,10 @@ export type DocMap = Record; export interface SinglesMap { SystemSettings?: SystemSettings; + AccountingSettings?: AccountingSettings; + InventorySettings?: InventorySettings; + PrintSettings?: PrintSettings; + Defaults?: Defaults; [key: string]: Doc | undefined; } diff --git a/models/baseModels/Defaults/Defaults.ts b/models/baseModels/Defaults/Defaults.ts index d23318b2..bfee0ff6 100644 --- a/models/baseModels/Defaults/Defaults.ts +++ b/models/baseModels/Defaults/Defaults.ts @@ -7,6 +7,10 @@ export class Defaults extends Doc { salesPaymentAccount?: string; purchasePaymentAccount?: string; + // Auto Stock Transfer + shipmentLocation?: string; + purchaseReceiptLocation?: string; + // Number Series salesInvoiceNumberSeries?: string; purchaseInvoiceNumberSeries?: string; diff --git a/models/baseModels/Invoice/Invoice.ts b/models/baseModels/Invoice/Invoice.ts index 368c5f17..865307ea 100644 --- a/models/baseModels/Invoice/Invoice.ts +++ b/models/baseModels/Invoice/Invoice.ts @@ -50,6 +50,7 @@ export abstract class Invoice extends Transactional { submitted?: boolean; cancelled?: boolean; makeAutoPayment?: boolean; + makeAutoStockTransfer?: boolean; get isSales() { return this.schemaName === 'SalesInvoice'; @@ -105,6 +106,18 @@ export abstract class Invoice extends Transactional { return null; } + get autoStockTransferLocation(): string | null { + const fieldname = this.isSales + ? 'shipmentLocation' + : 'purchaseReceiptLocation'; + const value = this.fyo.singles.Defaults?.[fieldname]; + if (typeof value === 'string' && value.length) { + return value; + } + + return null; + } + constructor(schema: Schema, data: DocValueMap, fyo: Fyo) { super(schema, data, fyo); this._setGetCurrencies(); @@ -139,6 +152,13 @@ export abstract class Invoice extends Transactional { await payment?.submit(); await this.load(); } + + if (this.makeAutoStockTransfer && this.autoStockTransferLocation) { + const stockTransfer = await this.getStockTransfer(true); + await stockTransfer?.sync(); + await stockTransfer?.submit(); + await this.load(); + } } async afterCancel() { @@ -418,6 +438,12 @@ export abstract class Invoice extends Transactional { formula: () => !!this.autoPaymentAccount, dependsOn: [], }, + makeAutoStockTransfer: { + formula: () => + !!this.fyo.singles.AccountingSettings?.enableInventory && + !!this.autoStockTransferLocation, + dependsOn: [], + }, }; getStockTransferred() { @@ -458,11 +484,18 @@ export abstract class Invoice extends Transactional { return true; } - if (!this.autoPaymentAccount) { + return !this.autoPaymentAccount; + }, + makeAutoStockTransfer: () => { + if (this.submitted) { return true; } - return false; + if (!this.fyo.singles.AccountingSettings?.enableInventory) { + return true; + } + + return !this.autoStockTransferLocation; }, setDiscountAmount: () => true || !this.enableDiscounting, discountAmount: () => @@ -486,6 +519,10 @@ export abstract class Invoice extends Transactional { static defaults: DefaultMap = { makeAutoPayment: (doc) => doc instanceof Invoice && !!doc.autoPaymentAccount, + makeAutoStockTransfer: (doc) => + !!doc.fyo.singles.AccountingSettings?.enableInventory && + doc instanceof Invoice && + !!doc.autoStockTransferLocation, numberSeries: (doc) => getNumberSeries(doc.schemaName, doc.fyo), terms: (doc) => { const defaults = doc.fyo.singles.Defaults as Defaults | undefined; @@ -574,7 +611,9 @@ export abstract class Invoice extends Transactional { return this.fyo.doc.getNewDoc(ModelNameEnum.Payment, data) as Payment; } - async getStockTransfer(): Promise { + async getStockTransfer( + isAuto: boolean = false + ): Promise { if (!this.isSubmitted) { return null; } @@ -604,9 +643,14 @@ export abstract class Invoice extends Transactional { backReference: this.name, }; - const location = - (this.fyo.singles.InventorySettings as InventorySettings) - .defaultLocation ?? null; + let location = this.autoStockTransferLocation; + if (!location) { + location = this.fyo.singles.InventorySettings?.defaultLocation ?? null; + } + + if (isAuto && !location) { + return null; + } const transfer = this.fyo.doc.getNewDoc(schemaName, data) as StockTransfer; for (const row of this.items ?? []) { @@ -615,6 +659,10 @@ export abstract class Invoice extends Transactional { } const itemDoc = (await row.loadAndGetLink('item')) as Item; + if (isAuto && (itemDoc.hasBatch || itemDoc.hasSerialNumber)) { + continue; + } + const item = row.item; const quantity = row.stockNotTransferred; const trackItem = itemDoc.trackItem; @@ -631,6 +679,21 @@ export abstract class Invoice extends Transactional { continue; } + if (isAuto) { + const stock = + (await this.fyo.db.getStockQuantity( + item, + location!, + undefined, + data.date + )) ?? 0; + console.log(quantity, stock); + + if (stock < quantity) { + continue; + } + } + await transfer.append('items', { item, quantity, diff --git a/schemas/app/Defaults.json b/schemas/app/Defaults.json index ab09679b..9b5e5c3d 100644 --- a/schemas/app/Defaults.json +++ b/schemas/app/Defaults.json @@ -20,6 +20,22 @@ "create": true, "section": "Auto Payments" }, + { + "fieldname": "shipmentLocation", + "label": "Shipment Location", + "fieldtype": "Link", + "target": "Location", + "create": true, + "section": "Auto Stock Transfer" + }, + { + "fieldname": "purchaseReceiptLocation", + "label": "Purchase Receipt Location", + "fieldtype": "Link", + "target": "Location", + "create": true, + "section": "Auto Stock Transfer" + }, { "fieldname": "salesInvoiceNumberSeries", "label": "Sales Invoice Number Series", diff --git a/schemas/app/Invoice.json b/schemas/app/Invoice.json index 29c10053..04775e4c 100644 --- a/schemas/app/Invoice.json +++ b/schemas/app/Invoice.json @@ -147,6 +147,11 @@ "readOnly": false, "tab": "Settings" }, + { + "abstract": true, + "fieldname": "makeAutoStockTransfer", + "tab": "Settings" + }, { "fieldname": "outstandingAmount", "label": "Outstanding Amount", diff --git a/schemas/app/PurchaseInvoice.json b/schemas/app/PurchaseInvoice.json index fca1587b..4cfa1f86 100644 --- a/schemas/app/PurchaseInvoice.json +++ b/schemas/app/PurchaseInvoice.json @@ -22,6 +22,14 @@ "target": "PurchaseReceipt", "section": "References" }, + { + "fieldname": "makeAutoStockTransfer", + "label": "Make Purchase Receipt On Submit", + "fieldtype": "Check", + "default": false, + "readOnly": false, + "tab": "Settings" + }, { "fieldname": "items", "label": "Items", diff --git a/schemas/app/SalesInvoice.json b/schemas/app/SalesInvoice.json index 34e3d66e..6125e1ae 100644 --- a/schemas/app/SalesInvoice.json +++ b/schemas/app/SalesInvoice.json @@ -22,6 +22,14 @@ "target": "Shipment", "section": "References" }, + { + "fieldname": "makeAutoStockTransfer", + "label": "Make Shipment On Submit", + "fieldtype": "Check", + "default": false, + "readOnly": false, + "tab": "Settings" + }, { "fieldname": "items", "label": "Items",