2
0
mirror of https://github.com/frappe/books.git synced 2025-01-10 18:24:40 +00:00

Merge pull request #652 from frappe/auto-stock-transfer

feat: auto stock transfer
This commit is contained in:
Alan 2023-06-06 01:20:47 -07:00 committed by GitHub
commit 25b230b9a2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 119 additions and 7 deletions

View File

@ -1,10 +1,14 @@
import { Fyo } from 'fyo'; import { Fyo } from 'fyo';
import { DocValue, DocValueMap } from 'fyo/core/types'; 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 { FieldType, Schema, SelectOption } from 'schemas/types';
import { QueryFilter } from 'utils/db/types'; import { QueryFilter } from 'utils/db/types';
import { RouteLocationRaw, Router } from 'vue-router'; import { RouteLocationRaw, Router } from 'vue-router';
import { Doc } from './doc'; 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 * The functions below are used for dynamic evaluation
@ -47,6 +51,10 @@ export type DocMap = Record<string, Doc | undefined>;
export interface SinglesMap { export interface SinglesMap {
SystemSettings?: SystemSettings; SystemSettings?: SystemSettings;
AccountingSettings?: AccountingSettings;
InventorySettings?: InventorySettings;
PrintSettings?: PrintSettings;
Defaults?: Defaults;
[key: string]: Doc | undefined; [key: string]: Doc | undefined;
} }

View File

@ -7,6 +7,10 @@ export class Defaults extends Doc {
salesPaymentAccount?: string; salesPaymentAccount?: string;
purchasePaymentAccount?: string; purchasePaymentAccount?: string;
// Auto Stock Transfer
shipmentLocation?: string;
purchaseReceiptLocation?: string;
// Number Series // Number Series
salesInvoiceNumberSeries?: string; salesInvoiceNumberSeries?: string;
purchaseInvoiceNumberSeries?: string; purchaseInvoiceNumberSeries?: string;

View File

@ -50,6 +50,7 @@ export abstract class Invoice extends Transactional {
submitted?: boolean; submitted?: boolean;
cancelled?: boolean; cancelled?: boolean;
makeAutoPayment?: boolean; makeAutoPayment?: boolean;
makeAutoStockTransfer?: boolean;
get isSales() { get isSales() {
return this.schemaName === 'SalesInvoice'; return this.schemaName === 'SalesInvoice';
@ -105,6 +106,18 @@ export abstract class Invoice extends Transactional {
return null; 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) { constructor(schema: Schema, data: DocValueMap, fyo: Fyo) {
super(schema, data, fyo); super(schema, data, fyo);
this._setGetCurrencies(); this._setGetCurrencies();
@ -139,6 +152,13 @@ export abstract class Invoice extends Transactional {
await payment?.submit(); await payment?.submit();
await this.load(); 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() { async afterCancel() {
@ -418,6 +438,12 @@ export abstract class Invoice extends Transactional {
formula: () => !!this.autoPaymentAccount, formula: () => !!this.autoPaymentAccount,
dependsOn: [], dependsOn: [],
}, },
makeAutoStockTransfer: {
formula: () =>
!!this.fyo.singles.AccountingSettings?.enableInventory &&
!!this.autoStockTransferLocation,
dependsOn: [],
},
}; };
getStockTransferred() { getStockTransferred() {
@ -458,11 +484,18 @@ export abstract class Invoice extends Transactional {
return true; return true;
} }
if (!this.autoPaymentAccount) { return !this.autoPaymentAccount;
},
makeAutoStockTransfer: () => {
if (this.submitted) {
return true; return true;
} }
return false; if (!this.fyo.singles.AccountingSettings?.enableInventory) {
return true;
}
return !this.autoStockTransferLocation;
}, },
setDiscountAmount: () => true || !this.enableDiscounting, setDiscountAmount: () => true || !this.enableDiscounting,
discountAmount: () => discountAmount: () =>
@ -486,6 +519,10 @@ export abstract class Invoice extends Transactional {
static defaults: DefaultMap = { static defaults: DefaultMap = {
makeAutoPayment: (doc) => makeAutoPayment: (doc) =>
doc instanceof Invoice && !!doc.autoPaymentAccount, doc instanceof Invoice && !!doc.autoPaymentAccount,
makeAutoStockTransfer: (doc) =>
!!doc.fyo.singles.AccountingSettings?.enableInventory &&
doc instanceof Invoice &&
!!doc.autoStockTransferLocation,
numberSeries: (doc) => getNumberSeries(doc.schemaName, doc.fyo), numberSeries: (doc) => getNumberSeries(doc.schemaName, doc.fyo),
terms: (doc) => { terms: (doc) => {
const defaults = doc.fyo.singles.Defaults as Defaults | undefined; 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; return this.fyo.doc.getNewDoc(ModelNameEnum.Payment, data) as Payment;
} }
async getStockTransfer(): Promise<StockTransfer | null> { async getStockTransfer(
isAuto: boolean = false
): Promise<StockTransfer | null> {
if (!this.isSubmitted) { if (!this.isSubmitted) {
return null; return null;
} }
@ -604,9 +643,14 @@ export abstract class Invoice extends Transactional {
backReference: this.name, backReference: this.name,
}; };
const location = let location = this.autoStockTransferLocation;
(this.fyo.singles.InventorySettings as InventorySettings) if (!location) {
.defaultLocation ?? null; location = this.fyo.singles.InventorySettings?.defaultLocation ?? null;
}
if (isAuto && !location) {
return null;
}
const transfer = this.fyo.doc.getNewDoc(schemaName, data) as StockTransfer; const transfer = this.fyo.doc.getNewDoc(schemaName, data) as StockTransfer;
for (const row of this.items ?? []) { for (const row of this.items ?? []) {
@ -615,6 +659,10 @@ export abstract class Invoice extends Transactional {
} }
const itemDoc = (await row.loadAndGetLink('item')) as Item; const itemDoc = (await row.loadAndGetLink('item')) as Item;
if (isAuto && (itemDoc.hasBatch || itemDoc.hasSerialNumber)) {
continue;
}
const item = row.item; const item = row.item;
const quantity = row.stockNotTransferred; const quantity = row.stockNotTransferred;
const trackItem = itemDoc.trackItem; const trackItem = itemDoc.trackItem;
@ -631,6 +679,21 @@ export abstract class Invoice extends Transactional {
continue; 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', { await transfer.append('items', {
item, item,
quantity, quantity,

View File

@ -20,6 +20,22 @@
"create": true, "create": true,
"section": "Auto Payments" "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", "fieldname": "salesInvoiceNumberSeries",
"label": "Sales Invoice Number Series", "label": "Sales Invoice Number Series",

View File

@ -147,6 +147,11 @@
"readOnly": false, "readOnly": false,
"tab": "Settings" "tab": "Settings"
}, },
{
"abstract": true,
"fieldname": "makeAutoStockTransfer",
"tab": "Settings"
},
{ {
"fieldname": "outstandingAmount", "fieldname": "outstandingAmount",
"label": "Outstanding Amount", "label": "Outstanding Amount",

View File

@ -22,6 +22,14 @@
"target": "PurchaseReceipt", "target": "PurchaseReceipt",
"section": "References" "section": "References"
}, },
{
"fieldname": "makeAutoStockTransfer",
"label": "Make Purchase Receipt On Submit",
"fieldtype": "Check",
"default": false,
"readOnly": false,
"tab": "Settings"
},
{ {
"fieldname": "items", "fieldname": "items",
"label": "Items", "label": "Items",

View File

@ -22,6 +22,14 @@
"target": "Shipment", "target": "Shipment",
"section": "References" "section": "References"
}, },
{
"fieldname": "makeAutoStockTransfer",
"label": "Make Shipment On Submit",
"fieldtype": "Check",
"default": false,
"readOnly": false,
"tab": "Settings"
},
{ {
"fieldname": "items", "fieldname": "items",
"label": "Items", "label": "Items",