2
0
mirror of https://github.com/frappe/books.git synced 2024-12-22 10:58:59 +00:00

fix: shift serial number creation to Transfer

This commit is contained in:
18alantom 2023-05-05 11:13:04 +05:30
parent 4384e32706
commit 6869ca9652
9 changed files with 88 additions and 47 deletions

View File

@ -2,16 +2,10 @@ import { ListViewSettings } from 'fyo/model/types';
import { getTransactionStatusColumn } from 'models/helpers';
import { PurchaseReceiptItem } from './PurchaseReceiptItem';
import { StockTransfer } from './StockTransfer';
import { createSerialNumbers } from './helpers';
export class PurchaseReceipt extends StockTransfer {
items?: PurchaseReceiptItem[];
override async afterSubmit(): Promise<void> {
await super.afterSubmit();
await createSerialNumbers(this);
}
static getListViewSettings(): ListViewSettings {
return {
columns: [

View File

@ -1,5 +1,4 @@
import { Fyo, t } from 'fyo';
import type { Doc } from 'fyo/model/doc';
import {
Action,
DefaultMap,
@ -20,13 +19,13 @@ import { SerialNumber } from './SerialNumber';
import { StockMovementItem } from './StockMovementItem';
import { Transfer } from './Transfer';
import {
createSerialNumbers,
canValidateSerialNumber,
getSerialNumberFromDoc,
updateSerialNumbers,
validateBatch,
validateSerialNumber,
validateSerialNumber
} from './helpers';
import { MovementType, MovementTypeEnum, SerialNumberStatus } from './types';
import { MovementType, MovementTypeEnum } from './types';
export class StockMovement extends Transfer {
name?: string;
@ -66,7 +65,6 @@ export class StockMovement extends Transfer {
async afterSubmit(): Promise<void> {
await super.afterSubmit();
await createSerialNumbers(this);
await updateSerialNumbers(this, false);
}
@ -147,7 +145,12 @@ export class StockMovement extends Transfer {
}
async function validateSerialNumberStatus(doc: StockMovement) {
for (const serialNumber of getSerialNumberFromDoc(doc)) {
for (const { serialNumber, item } of getSerialNumberFromDoc(doc)) {
const cannotValidate = !(await canValidateSerialNumber(item, serialNumber));
if (cannotValidate) {
continue;
}
const snDoc = await doc.fyo.doc.getDoc(
ModelNameEnum.SerialNumber,
serialNumber
@ -161,35 +164,26 @@ async function validateSerialNumberStatus(doc: StockMovement) {
if (doc.movementType === 'MaterialReceipt' && status !== 'Inactive') {
throw new ValidationError(
t`Active Serial Number ${serialNumber} cannot be used for Material Issue`
t`Non Inactive Serial Number ${serialNumber} cannot be used for Material Receipt`
);
}
if (doc.movementType === 'MaterialIssue' && status !== 'Active') {
validateMaterialIssueSerialNumber(serialNumber, status);
throw new ValidationError(
t`Inactive Serial Number ${serialNumber} cannot be used for Material Issue`
t`Non Active Serial Number ${serialNumber} cannot be used for Material Issue`
);
}
if (doc.movementType === 'MaterialTransfer' && status !== 'Active') {
throw new ValidationError(
t`Non Active Serial Number ${serialNumber} cannot be used for Material Transfer`
);
}
if (item.fromLocation && status !== 'Active') {
throw new ValidationError(
t`Non Active Serial Number ${serialNumber} cannot be used as Manufacture raw material`
);
}
}
}
async function validateMaterialReceiptSerialNumber(
serialNumber: string,
status: string
) {
if (status === 'Inactive') {
return;
}
}
async function validateMaterialIssueSerialNumber(
serialNumber: string,
status: SerialNumberStatus
) {
if (status === 'Active') {
return;
}
throw new ValidationError(t`Serial Number ${serialNumber} is not Active.`);
}

View File

@ -15,8 +15,9 @@ import { Money } from 'pesa';
import { safeParseFloat } from 'utils/index';
import { StockMovement } from './StockMovement';
import { MovementTypeEnum } from './types';
import { TransferItem } from './TransferItem';
export class StockMovementItem extends Doc {
export class StockMovementItem extends TransferItem {
name?: string;
item?: string;
fromLocation?: string;
@ -30,10 +31,12 @@ export class StockMovementItem extends Doc {
rate?: Money;
amount?: Money;
parentdoc?: StockMovement;
batch?: string;
serialNumber?: string;
parentdoc?: StockMovement;
get isIssue() {
return this.parentdoc?.movementType === MovementTypeEnum.MaterialIssue;
}

View File

@ -17,15 +17,16 @@ import { addItem, getLedgerLinkAction, getNumberSeries } from 'models/helpers';
import { ModelNameEnum } from 'models/types';
import { Money } from 'pesa';
import { TargetField } from 'schemas/types';
import { SerialNumber } from './SerialNumber';
import { StockTransferItem } from './StockTransferItem';
import { Transfer } from './Transfer';
import {
canValidateSerialNumber,
getSerialNumberFromDoc,
updateSerialNumbers,
validateBatch,
validateSerialNumber,
} from './helpers';
import { SerialNumber } from './SerialNumber';
export abstract class StockTransfer extends Transfer {
name?: string;
@ -311,7 +312,12 @@ export abstract class StockTransfer extends Transfer {
}
async function validateSerialNumberStatus(doc: StockTransfer) {
for (const serialNumber of getSerialNumberFromDoc(doc)) {
for (const { serialNumber, item } of getSerialNumberFromDoc(doc)) {
const cannotValidate = !(await canValidateSerialNumber(item, serialNumber));
if (cannotValidate) {
continue;
}
const snDoc = await doc.fyo.doc.getDoc(
ModelNameEnum.SerialNumber,
serialNumber

View File

@ -12,8 +12,9 @@ import { ModelNameEnum } from 'models/types';
import { Money } from 'pesa';
import { safeParseFloat } from 'utils/index';
import { StockTransfer } from './StockTransfer';
import { TransferItem } from './TransferItem';
export class StockTransferItem extends Doc {
export class StockTransferItem extends TransferItem {
item?: string;
location?: string;
@ -25,8 +26,10 @@ export class StockTransferItem extends Doc {
rate?: Money;
amount?: Money;
description?: string;
hsnCode?: number;
batch?: string;
serialNumber?: string;

View File

@ -1,9 +1,12 @@
import { Transactional } from 'models/Transactional/Transactional';
import { StockManager } from './StockManager';
import { SMTransferDetails } from './types';
import type { SMTransferDetails } from './types';
import type { TransferItem } from './TransferItem';
import { createSerialNumbers } from './helpers';
export abstract class Transfer extends Transactional {
date?: Date;
items?: TransferItem[];
async beforeSubmit(): Promise<void> {
await super.beforeSubmit();
@ -13,6 +16,7 @@ export abstract class Transfer extends Transactional {
async afterSubmit(): Promise<void> {
await super.afterSubmit();
await createSerialNumbers(this);
const transferDetails = this._getTransferDetails();
await this._getStockManager().createTransfers(transferDetails);
}

View File

@ -0,0 +1,21 @@
import { Doc } from 'fyo/model/doc';
import type { Transfer } from './Transfer';
import type { Money } from 'pesa';
export class TransferItem extends Doc {
item?: string;
unit?: string;
transferUnit?: string;
quantity?: number;
transferQuantity?: number;
unitConversionFactor?: number;
rate?: Money;
amount?: Money;
batch?: string;
serialNumber?: string;
parentdoc?: Transfer;
}

View File

@ -8,8 +8,9 @@ import type { StockMovement } from './StockMovement';
import type { StockMovementItem } from './StockMovementItem';
import type { StockTransfer } from './StockTransfer';
import type { StockTransferItem } from './StockTransferItem';
import { Transfer } from './Transfer';
import { TransferItem } from './TransferItem';
import type { SerialNumberStatus } from './types';
import type { PurchaseReceipt } from './PurchaseReceipt';
export async function validateBatch(
doc: StockMovement | StockTransfer | Invoice
@ -171,14 +172,17 @@ export function getSerialNumberFromDoc(doc: StockTransfer | StockMovement) {
}
return doc.items
.map((item) => getSerialNumbers(item.serialNumber ?? ''))
.map((item) =>
getSerialNumbers(item.serialNumber ?? '').map((serialNumber) => ({
serialNumber,
item,
}))
)
.flat()
.filter(Boolean);
}
export async function createSerialNumbers(
doc: PurchaseReceipt | StockMovement
) {
export async function createSerialNumbers(doc: Transfer) {
const items = doc.items ?? [];
const serialNumberCreateList = items
.map((item) => {
@ -208,7 +212,7 @@ export async function createSerialNumbers(
}
}
function isSerialNumberIncoming(item: StockTransferItem | StockMovementItem) {
function isSerialNumberIncoming(item: TransferItem) {
if (item.parentdoc?.schemaName === ModelNameEnum.Shipment) {
return false;
}
@ -220,6 +224,17 @@ function isSerialNumberIncoming(item: StockTransferItem | StockMovementItem) {
return !!item.toLocation && !item.fromLocation;
}
export async function canValidateSerialNumber(
item: StockTransferItem | StockMovementItem,
serialNumber: string
) {
if (!isSerialNumberIncoming(item)) {
return true;
}
return await item.fyo.db.exists(ModelNameEnum.SerialNumber, serialNumber);
}
export async function updateSerialNumbers(
doc: StockTransfer | StockMovement,
isCancel: boolean

View File

@ -29,6 +29,7 @@
"label": "Status",
"fieldtype": "Select",
"default": "Inactive",
"readOnly": true,
"options": [
{
"value": "Inactive",