Skip to content

Commit

Permalink
Merge pull request #788 from frappe/mildred/151-quotations
Browse files Browse the repository at this point in the history
feat: #151 Quotations
  • Loading branch information
mildred committed Jan 8, 2024
2 parents b1c94c3 + 4dfeb98 commit bcd0cc8
Show file tree
Hide file tree
Showing 22 changed files with 321 additions and 20 deletions.
2 changes: 2 additions & 0 deletions backend/patches/updateSchemas.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ const defaultNumberSeriesMap = {
[ModelNameEnum.JournalEntry]: 'JV-',
[ModelNameEnum.SalesInvoice]: 'SINV-',
[ModelNameEnum.PurchaseInvoice]: 'PINV-',
[ModelNameEnum.SalesQuote]: 'SQUOT-',
} as Record<ModelNameEnum, string>;

async function execute(dm: DatabaseManager) {
Expand Down Expand Up @@ -209,6 +210,7 @@ async function copyTransactionalTables(
ModelNameEnum.Payment,
ModelNameEnum.SalesInvoice,
ModelNameEnum.PurchaseInvoice,
ModelNameEnum.SalesQuote,
];

for (const sn of schemaNames) {
Expand Down
7 changes: 7 additions & 0 deletions models/baseModels/Defaults/Defaults.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ export class Defaults extends Doc {
purchaseReceiptLocation?: string;

// Number Series
salesQuoteNumberSeries?: string;
salesInvoiceNumberSeries?: string;
purchaseInvoiceNumberSeries?: string;
journalEntryNumberSeries?: string;
Expand All @@ -29,6 +30,7 @@ export class Defaults extends Doc {
purchaseReceiptTerms?: string;

// Print Templates
salesQuotePrintTemplate?: string;
salesInvoicePrintTemplate?: string;
purchaseInvoicePrintTemplate?: string;
journalEntryPrintTemplate?: string;
Expand All @@ -46,6 +48,9 @@ export class Defaults extends Doc {
salesPaymentAccount: () => ({ isGroup: false, accountType: 'Cash' }),
purchasePaymentAccount: () => ({ isGroup: false, accountType: 'Cash' }),
// Number Series
salesQuoteNumberSeries: () => ({
referenceType: ModelNameEnum.SalesQuote,
}),
salesInvoiceNumberSeries: () => ({
referenceType: ModelNameEnum.SalesInvoice,
}),
Expand All @@ -68,6 +73,7 @@ export class Defaults extends Doc {
referenceType: ModelNameEnum.PurchaseReceipt,
}),
// Print Templates
salesQuotePrintTemplate: () => ({ type: ModelNameEnum.SalesQuote }),
salesInvoicePrintTemplate: () => ({ type: ModelNameEnum.SalesInvoice }),
purchaseInvoicePrintTemplate: () => ({
type: ModelNameEnum.PurchaseInvoice,
Expand Down Expand Up @@ -118,4 +124,5 @@ export const numberSeriesDefaultsMap: Record<
[ModelNameEnum.StockMovement]: 'stockMovementNumberSeries',
[ModelNameEnum.Shipment]: 'shipmentNumberSeries',
[ModelNameEnum.PurchaseReceipt]: 'purchaseReceiptNumberSeries',
[ModelNameEnum.SalesQuote]: 'salesQuoteNumberSeries',
};
13 changes: 10 additions & 3 deletions models/baseModels/Invoice/Invoice.ts
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,13 @@ export abstract class Invoice extends Transactional {
returnAgainst?: string;

get isSales() {
return this.schemaName === 'SalesInvoice';
return (
this.schemaName === 'SalesInvoice' || this.schemaName == 'SalesQuote'
);
}

get isQuote() {
return this.schemaName == 'SalesQuote';
}

get enableDiscounting() {
Expand Down Expand Up @@ -493,7 +499,7 @@ export abstract class Invoice extends Transactional {
}

async _updateIsItemsReturned() {
if (!this.isReturn || !this.returnAgainst) {
if (!this.isReturn || !this.returnAgainst || this.isQuote) {
return;
}

Expand All @@ -515,7 +521,7 @@ export abstract class Invoice extends Transactional {
}

async _validateHasLinkedReturnInvoices() {
if (!this.name || this.isReturn) {
if (!this.name || this.isReturn || this.isQuote) {
return;
}

Expand Down Expand Up @@ -685,6 +691,7 @@ export abstract class Invoice extends Transactional {
attachment: () =>
!(this.attachment || !(this.isSubmitted || this.isCancelled)),
backReference: () => !this.backReference,
quote: () => !this.quote,
priceList: () => !this.fyo.singles.AccountingSettings?.enablePriceList,
returnAgainst: () =>
(this.isSubmitted || this.isCancelled) && !this.returnAgainst,
Expand Down
5 changes: 4 additions & 1 deletion models/baseModels/InvoiceItem/InvoiceItem.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,10 @@ export abstract class InvoiceItem extends Doc {
itemTaxedTotal?: Money;

get isSales() {
return this.schemaName === 'SalesInvoiceItem';
return (
this.schemaName === 'SalesInvoiceItem' ||
this.schemaName === 'SalesQuoteItem'
);
}

get date() {
Expand Down
1 change: 1 addition & 0 deletions models/baseModels/PrintTemplate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ export class PrintTemplate extends Doc {

const models = [
ModelNameEnum.SalesInvoice,
ModelNameEnum.SalesQuote,
ModelNameEnum.PurchaseInvoice,
ModelNameEnum.JournalEntry,
ModelNameEnum.Payment,
Expand Down
67 changes: 67 additions & 0 deletions models/baseModels/SalesQuote/SalesQuote.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
import { Fyo } from 'fyo';
import { DocValueMap } from 'fyo/core/types';
import { Action, ListViewSettings } from 'fyo/model/types';
import { ModelNameEnum } from 'models/types';
import { getQuoteActions, getTransactionStatusColumn } from '../../helpers';
import { Invoice } from '../Invoice/Invoice';
import { SalesQuoteItem } from '../SalesQuoteItem/SalesQuoteItem';
import { Defaults } from '../Defaults/Defaults';

export class SalesQuote extends Invoice {
items?: SalesQuoteItem[];

// This is an inherited method and it must keep the async from the parent
// class
// eslint-disable-next-line @typescript-eslint/require-await
async getPosting() {
return null;
}

async getInvoice(): Promise<Invoice | null> {
if (!this.isSubmitted) {
return null;
}

const schemaName = ModelNameEnum.SalesInvoice;
const defaults = (this.fyo.singles.Defaults as Defaults) ?? {};
const terms = defaults.salesInvoiceTerms ?? '';
const numberSeries = defaults.salesInvoiceNumberSeries ?? undefined;

const data: DocValueMap = {
...this.getValidDict(false, true),
date: new Date().toISOString(),
terms,
numberSeries,
quote: this.name,
items: [],
};

const invoice = this.fyo.doc.getNewDoc(schemaName, data) as Invoice;
for (const row of this.items ?? []) {
await invoice.append('items', row.getValidDict(false, true));
}

if (!invoice.items?.length) {
return null;
}

return invoice;
}

static getListViewSettings(): ListViewSettings {
return {
columns: [
'name',
getTransactionStatusColumn(),
'party',
'date',
'baseGrandTotal',
'outstandingAmount',
],
};
}

static getActions(fyo: Fyo): Action[] {
return getQuoteActions(fyo, ModelNameEnum.SalesQuote);
}
}
3 changes: 3 additions & 0 deletions models/baseModels/SalesQuoteItem/SalesQuoteItem.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import { InvoiceItem } from '../InvoiceItem/InvoiceItem';

export class SalesQuoteItem extends InvoiceItem {}
23 changes: 20 additions & 3 deletions models/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,18 @@ import {
} from './baseModels/Account/types';
import { numberSeriesDefaultsMap } from './baseModels/Defaults/Defaults';
import { Invoice } from './baseModels/Invoice/Invoice';
import { SalesQuote } from './baseModels/SalesQuote/SalesQuote';
import { StockMovement } from './inventory/StockMovement';
import { StockTransfer } from './inventory/StockTransfer';
import { InvoiceStatus, ModelNameEnum } from './types';

export function getQuoteActions(
fyo: Fyo,
schemaName: ModelNameEnum.SalesQuote
): Action[] {
return [getMakeInvoiceAction(fyo, schemaName)];
}

export function getInvoiceActions(
fyo: Fyo,
schemaName: ModelNameEnum.SalesInvoice | ModelNameEnum.PurchaseInvoice
Expand Down Expand Up @@ -67,7 +75,10 @@ export function getMakeStockTransferAction(

export function getMakeInvoiceAction(
fyo: Fyo,
schemaName: ModelNameEnum.Shipment | ModelNameEnum.PurchaseReceipt
schemaName:
| ModelNameEnum.Shipment
| ModelNameEnum.PurchaseReceipt
| ModelNameEnum.SalesQuote
): Action {
let label = fyo.t`Sales Invoice`;
if (schemaName === ModelNameEnum.PurchaseReceipt) {
Expand All @@ -77,9 +88,15 @@ export function getMakeInvoiceAction(
return {
label,
group: fyo.t`Create`,
condition: (doc: Doc) => doc.isSubmitted && !doc.backReference,
condition: (doc: Doc) => {
if (schemaName === ModelNameEnum.SalesQuote) {
return doc.isSubmitted;
} else {
return doc.isSubmitted && !doc.backReference;
}
},
action: async (doc: Doc) => {
const invoice = await (doc as StockTransfer).getInvoice();
const invoice = await (doc as SalesQuote | StockTransfer).getInvoice();
if (!invoice || !invoice.name) {
return;
}
Expand Down
4 changes: 4 additions & 0 deletions models/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ import { PurchaseInvoice } from './baseModels/PurchaseInvoice/PurchaseInvoice';
import { PurchaseInvoiceItem } from './baseModels/PurchaseInvoiceItem/PurchaseInvoiceItem';
import { SalesInvoice } from './baseModels/SalesInvoice/SalesInvoice';
import { SalesInvoiceItem } from './baseModels/SalesInvoiceItem/SalesInvoiceItem';
import { SalesQuote } from './baseModels/SalesQuote/SalesQuote';
import { SalesQuoteItem } from './baseModels/SalesQuoteItem/SalesQuoteItem';
import { SetupWizard } from './baseModels/SetupWizard/SetupWizard';
import { Tax } from './baseModels/Tax/Tax';
import { TaxSummary } from './baseModels/TaxSummary/TaxSummary';
Expand Down Expand Up @@ -61,6 +63,8 @@ export const models = {
PurchaseInvoiceItem,
SalesInvoice,
SalesInvoiceItem,
SalesQuote,
SalesQuoteItem,
SerialNumber,
SetupWizard,
PrintTemplate,
Expand Down
2 changes: 2 additions & 0 deletions models/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ export enum ModelNameEnum {
PurchaseInvoiceItem = 'PurchaseInvoiceItem',
SalesInvoice = 'SalesInvoice',
SalesInvoiceItem = 'SalesInvoiceItem',
SalesQuote = 'SalesQuote',
SalesQuoteItem = 'SalesQuoteItem',
SerialNumber = 'SerialNumber',
SetupWizard = 'SetupWizard',
Tax = 'Tax',
Expand Down
15 changes: 15 additions & 0 deletions schemas/app/Defaults.json
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,14 @@
"create": true,
"section": "Number Series"
},
{
"fieldname": "salesQuoteNumberSeries",
"label": "Sales Quote Number Series",
"fieldtype": "Link",
"target": "NumberSeries",
"create": true,
"section": "Number Series"
},
{
"fieldname": "salesInvoiceTerms",
"label": "Sales Invoice Terms",
Expand All @@ -116,6 +124,13 @@
"fieldtype": "Text",
"section": "Terms"
},
{
"fieldname": "salesQuotePrintTemplate",
"label": "Sales Quote Print Template",
"fieldtype": "Link",
"target": "PrintTemplate",
"section": "Print Templates"
},
{
"fieldname": "salesInvoicePrintTemplate",
"label": "Sales Invoice Print Template",
Expand Down
4 changes: 4 additions & 0 deletions schemas/app/NumberSeries.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,10 @@
"value": "SalesInvoice",
"label": "Sales Invoice"
},
{
"value": "SalesQuote",
"label": "Sales Quote"
},
{
"value": "PurchaseInvoice",
"label": "Purchase Invoice"
Expand Down
8 changes: 8 additions & 0 deletions schemas/app/SalesInvoice.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,14 @@
"target": "Shipment",
"section": "References"
},
{
"fieldname": "quote",
"label": "Quote Reference",
"fieldtype": "Link",
"target": "SalesQuote",
"section": "References",
"required": false
},
{
"fieldname": "makeAutoStockTransfer",
"label": "Make Shipment On Submit",
Expand Down
46 changes: 46 additions & 0 deletions schemas/app/SalesQuote.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
{
"name": "SalesQuote",
"label": "Quote",
"extends": "Invoice",
"naming": "numberSeries",
"showTitle": true,
"fields": [
{
"fieldname": "numberSeries",
"label": "Number Series",
"fieldtype": "Link",
"target": "NumberSeries",
"create": true,
"required": true,
"default": "SQUOT-",
"section": "Default"
},
{
"fieldname": "party",
"label": "Customer",
"fieldtype": "Link",
"target": "Party",
"create": true,
"required": true,
"section": "Default"
},
{
"fieldname": "items",
"label": "Items",
"fieldtype": "Table",
"target": "SalesQuoteItem",
"required": true,
"edit": true,
"section": "Items"
}
],
"keywordFields": ["name", "party"],
"removeFields": [
"account",
"stockNotTransferred",
"backReference",
"makeAutoStockTransfer",
"returnAgainst",
"isReturned"
]
}
5 changes: 5 additions & 0 deletions schemas/app/SalesQuoteItem.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"name": "SalesQuoteItem",
"label": "Sales Quote Item",
"extends": "InvoiceItem"
}
4 changes: 4 additions & 0 deletions schemas/schemas.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ import PurchaseInvoice from './app/PurchaseInvoice.json';
import PurchaseInvoiceItem from './app/PurchaseInvoiceItem.json';
import SalesInvoice from './app/SalesInvoice.json';
import SalesInvoiceItem from './app/SalesInvoiceItem.json';
import SalesQuote from './app/SalesQuote.json';
import SalesQuoteItem from './app/SalesQuoteItem.json';
import SetupWizard from './app/SetupWizard.json';
import Tax from './app/Tax.json';
import TaxDetail from './app/TaxDetail.json';
Expand Down Expand Up @@ -108,10 +110,12 @@ export const appSchemas: Schema[] | SchemaStub[] = [
Invoice as Schema,
SalesInvoice as Schema,
PurchaseInvoice as Schema,
SalesQuote as Schema,

InvoiceItem as Schema,
SalesInvoiceItem as SchemaStub,
PurchaseInvoiceItem as SchemaStub,
SalesQuoteItem as SchemaStub,

PriceList as Schema,
PriceListItem as SchemaStub,
Expand Down
Loading

0 comments on commit bcd0cc8

Please sign in to comment.