mirror of
https://github.com/frappe/books.git
synced 2025-01-10 18:24:40 +00:00
Merge pull request #359 from 18alantom/custom-number-series
feat: custom number series
This commit is contained in:
commit
b4397a9132
@ -30,8 +30,18 @@ class SqliteDatabase extends Database {
|
||||
// create temp table
|
||||
await this.createTable(doctype, tempName);
|
||||
|
||||
// copy from old to new table
|
||||
await this.knex(tempName).insert(this.knex.select().from(doctype));
|
||||
try {
|
||||
// copy from old to new table
|
||||
await this.knex(tempName).insert(this.knex.select().from(doctype));
|
||||
} catch (err) {
|
||||
|
||||
await this.sql('ROLLBACK');
|
||||
await this.sql('PRAGMA foreign_keys=ON');
|
||||
|
||||
const rows = await this.knex.select().from(doctype);
|
||||
await this.prestigeTheTable(doctype, rows);
|
||||
return;
|
||||
}
|
||||
|
||||
// drop old table
|
||||
await this.knex.schema.dropTable(doctype);
|
||||
@ -110,6 +120,7 @@ class SqliteDatabase extends Database {
|
||||
// Alter table hacx for sqlite in case of schema change.
|
||||
const tempName = `__${tableName}`;
|
||||
await this.knex.schema.dropTableIfExists(tempName);
|
||||
|
||||
await this.knex.raw('PRAGMA foreign_keys=OFF');
|
||||
await this.createTable(tableName, tempName);
|
||||
|
||||
|
@ -1,3 +1,4 @@
|
||||
const { getPaddedName } = require('@/utils');
|
||||
const frappe = require('frappe');
|
||||
const { getRandomString } = require('frappe/utils');
|
||||
|
||||
@ -28,11 +29,23 @@ module.exports = {
|
||||
return;
|
||||
}
|
||||
|
||||
// Current, per doc number series
|
||||
if (doc.numberSeries) {
|
||||
doc.name = await this.getSeriesNext(doc.numberSeries, doc.doctype);
|
||||
return;
|
||||
}
|
||||
|
||||
// if(doc.meta)
|
||||
|
||||
// Legacy, using doc settings for number series
|
||||
if (doc.meta.settings) {
|
||||
const numberSeries = (await doc.getSettings()).numberSeries;
|
||||
if (numberSeries) {
|
||||
doc.name = await this.getSeriesNext(numberSeries, doc.doctype);
|
||||
if (!numberSeries) {
|
||||
return;
|
||||
}
|
||||
|
||||
doc.name = await this.getSeriesNext(numberSeries, doc.doctype);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@ -78,33 +91,34 @@ module.exports = {
|
||||
|
||||
async getSeriesNext(prefix, doctype) {
|
||||
let series;
|
||||
|
||||
try {
|
||||
series = await frappe.getDoc('NumberSeries', prefix);
|
||||
} catch (e) {
|
||||
if (!e.statusCode || e.statusCode !== 404) {
|
||||
throw e;
|
||||
}
|
||||
await this.createNumberSeries(prefix);
|
||||
|
||||
await this.createNumberSeries(prefix, doctype);
|
||||
series = await frappe.getDoc('NumberSeries', prefix);
|
||||
}
|
||||
let next = await series.next(doctype);
|
||||
return prefix + next;
|
||||
|
||||
return await series.next(doctype);
|
||||
},
|
||||
|
||||
async createNumberSeries(prefix, setting, start = 1001) {
|
||||
if (!(await frappe.db.exists('NumberSeries', prefix))) {
|
||||
const series = frappe.newDoc({
|
||||
doctype: 'NumberSeries',
|
||||
name: prefix,
|
||||
current: start,
|
||||
});
|
||||
await series.insert();
|
||||
|
||||
if (setting) {
|
||||
const settingDoc = await frappe.getSingle(setting);
|
||||
settingDoc.numberSeries = series.name;
|
||||
await settingDoc.update();
|
||||
}
|
||||
async createNumberSeries(prefix, referenceType, start = 1001) {
|
||||
const exists = await frappe.db.exists('NumberSeries', prefix);
|
||||
if (exists) {
|
||||
return;
|
||||
}
|
||||
|
||||
const series = frappe.newDoc({
|
||||
doctype: 'NumberSeries',
|
||||
name: prefix,
|
||||
start,
|
||||
referenceType,
|
||||
});
|
||||
|
||||
await series.insert();
|
||||
},
|
||||
};
|
||||
|
@ -1,5 +1,18 @@
|
||||
const { t } = require('frappe');
|
||||
|
||||
const referenceTypeMap = {
|
||||
SalesInvoice: t`Invoice`,
|
||||
PurchaseInvoice: t`Bill`,
|
||||
Payment: t`Payment`,
|
||||
JournalEntry: t`Journal Entry`,
|
||||
Quotation: t`Quotation`,
|
||||
SalesOrder: t`SalesOrder`,
|
||||
Fulfillment: t`Fulfillment`,
|
||||
PurchaseOrder: t`PurchaseOrder`,
|
||||
PurchaseReceipt: t`PurchaseReceipt`,
|
||||
'-': t`None`,
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
name: 'NumberSeries',
|
||||
documentClass: require('./NumberSeriesDocument.js'),
|
||||
@ -14,11 +27,38 @@ module.exports = {
|
||||
fieldtype: 'Data',
|
||||
required: 1,
|
||||
},
|
||||
{
|
||||
fieldname: 'start',
|
||||
label: t`Start`,
|
||||
fieldtype: 'Int',
|
||||
default: 1001,
|
||||
required: 1,
|
||||
minvalue: 0,
|
||||
},
|
||||
{
|
||||
fieldname: 'padZeros',
|
||||
label: t`Pad Zeros`,
|
||||
fieldtype: 'Int',
|
||||
default: 4,
|
||||
required: 1,
|
||||
},
|
||||
{
|
||||
fieldname: 'referenceType',
|
||||
label: t`Reference Type`,
|
||||
fieldtype: 'Select',
|
||||
options: Object.keys(referenceTypeMap),
|
||||
map: referenceTypeMap,
|
||||
default: '-',
|
||||
required: 1,
|
||||
readOnly: 1,
|
||||
},
|
||||
{
|
||||
fieldname: 'current',
|
||||
label: t`Current`,
|
||||
fieldtype: 'Int',
|
||||
required: 1,
|
||||
readOnly: 1,
|
||||
},
|
||||
],
|
||||
quickEditFields: ['start', 'padZeros', 'referenceType'],
|
||||
};
|
||||
|
@ -1,12 +1,14 @@
|
||||
const { getPaddedName } = require('@/utils');
|
||||
const frappe = require('frappe');
|
||||
const BaseDocument = require('frappe/model/document');
|
||||
|
||||
module.exports = class NumberSeries extends BaseDocument {
|
||||
validate() {
|
||||
if (this.current === null || this.current === undefined) {
|
||||
this.current = 0;
|
||||
if (!this.current) {
|
||||
this.current = this.start;
|
||||
}
|
||||
}
|
||||
|
||||
async next(doctype) {
|
||||
this.validate();
|
||||
|
||||
@ -17,13 +19,19 @@ module.exports = class NumberSeries extends BaseDocument {
|
||||
|
||||
this.current++;
|
||||
await this.update();
|
||||
return this.current;
|
||||
return this.getPaddedName(this.current);
|
||||
}
|
||||
|
||||
async checkIfCurrentExists(doctype) {
|
||||
if (!doctype) {
|
||||
return true;
|
||||
}
|
||||
return await frappe.db.exists(doctype, this.name + this.current);
|
||||
|
||||
const name = this.getPaddedName(this.current);
|
||||
return await frappe.db.exists(doctype, name);
|
||||
}
|
||||
|
||||
getPaddedName(next) {
|
||||
return getPaddedName(this.name, next, this.padZeros);
|
||||
}
|
||||
};
|
||||
|
@ -1,4 +1,15 @@
|
||||
export const DEFAULT_INTERNAL_PRECISION = 11;
|
||||
export const DEFAULT_DISPLAY_PRECISION = 2;
|
||||
export const DEFAULT_LOCALE = 'en-IN';
|
||||
export const DEFAULT_LANGUAGE = 'English';
|
||||
export const DEFAULT_LANGUAGE = 'English';
|
||||
export const DEFAULT_NUMBER_SERIES = {
|
||||
SalesInvoice: 'SINV-',
|
||||
PurchaseInvoice: 'PINV-',
|
||||
Payment: 'PAY-',
|
||||
JournalEntry: 'JV-',
|
||||
Quotation: 'QTN-',
|
||||
SalesOrder: 'SO-',
|
||||
Fulfillment: 'OF-',
|
||||
PurchaseOrder: 'PO-',
|
||||
PurchaseReceipt: 'PREC-',
|
||||
};
|
||||
|
@ -1,5 +1,6 @@
|
||||
import { t } from 'frappe';
|
||||
import model from 'frappe/model';
|
||||
import { DEFAULT_NUMBER_SERIES } from '../../../frappe/utils/consts';
|
||||
import Quotation from '../Quotation/Quotation';
|
||||
|
||||
export default model.extend(Quotation, {
|
||||
@ -11,5 +12,16 @@ export default model.extend(Quotation, {
|
||||
fieldname: 'items',
|
||||
childtype: 'FulfillmentItem',
|
||||
},
|
||||
{
|
||||
fieldname: 'numberSeries',
|
||||
label: t`Number Series`,
|
||||
fieldtype: 'Link',
|
||||
target: 'NumberSeries',
|
||||
required: 1,
|
||||
getFilters: () => {
|
||||
return { referenceType: 'Fulfillment' };
|
||||
},
|
||||
default: DEFAULT_NUMBER_SERIES['FulFillment'],
|
||||
},
|
||||
],
|
||||
});
|
||||
|
@ -5,10 +5,5 @@ import QuotationSettings from '../QuotationSettings/QuotationSettings';
|
||||
export default model.extend(QuotationSettings, {
|
||||
name: 'FulfillmentSettings',
|
||||
label: t`Fulfillment Settings`,
|
||||
fields: [
|
||||
{
|
||||
fieldname: 'numberSeries',
|
||||
default: 'OF',
|
||||
},
|
||||
],
|
||||
fields: [],
|
||||
});
|
||||
|
@ -1,6 +1,7 @@
|
||||
import { t } from 'frappe';
|
||||
import { DateTime } from 'luxon';
|
||||
import { ledgerLink } from '../../../accounting/utils';
|
||||
import { DEFAULT_NUMBER_SERIES } from '../../../frappe/utils/consts';
|
||||
|
||||
export default {
|
||||
label: t`Journal Entry`,
|
||||
@ -72,6 +73,17 @@ export default {
|
||||
default: 0,
|
||||
readOnly: 1,
|
||||
},
|
||||
{
|
||||
fieldname: 'numberSeries',
|
||||
label: t`Number Series`,
|
||||
fieldtype: 'Link',
|
||||
target: 'NumberSeries',
|
||||
required: 1,
|
||||
getFilters: () => {
|
||||
return { referenceType: 'JournalEntry' };
|
||||
},
|
||||
default: DEFAULT_NUMBER_SERIES['JournalEntry'],
|
||||
},
|
||||
],
|
||||
actions: [ledgerLink],
|
||||
};
|
||||
|
@ -6,14 +6,5 @@ export default {
|
||||
isSingle: 1,
|
||||
isChild: 0,
|
||||
keywordFields: [],
|
||||
fields: [
|
||||
{
|
||||
fieldname: 'numberSeries',
|
||||
label: t`Number Series`,
|
||||
fieldtype: 'Link',
|
||||
target: 'NumberSeries',
|
||||
required: 1,
|
||||
default: 'JV',
|
||||
},
|
||||
],
|
||||
fields: [],
|
||||
};
|
||||
|
@ -1,5 +1,6 @@
|
||||
import frappe, { t } from 'frappe';
|
||||
import utils from '../../../accounting/utils';
|
||||
import { DEFAULT_NUMBER_SERIES } from '../../../frappe/utils/consts';
|
||||
|
||||
export default {
|
||||
name: 'Payment',
|
||||
@ -81,6 +82,17 @@ export default {
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
fieldname: 'numberSeries',
|
||||
label: t`Number Series`,
|
||||
fieldtype: 'Link',
|
||||
target: 'NumberSeries',
|
||||
required: 1,
|
||||
getFilters: () => {
|
||||
return { referenceType: 'Payment' };
|
||||
},
|
||||
default: DEFAULT_NUMBER_SERIES['Payment'],
|
||||
},
|
||||
{
|
||||
fieldname: 'paymentMethod',
|
||||
label: t`Payment Method`,
|
||||
@ -162,6 +174,7 @@ export default {
|
||||
],
|
||||
|
||||
quickEditFields: [
|
||||
'numberSeries',
|
||||
'party',
|
||||
'date',
|
||||
'paymentMethod',
|
||||
|
@ -6,14 +6,5 @@ export default {
|
||||
isSingle: 1,
|
||||
isChild: 0,
|
||||
keywordFields: [],
|
||||
fields: [
|
||||
{
|
||||
fieldname: 'numberSeries',
|
||||
label: t`Number Series`,
|
||||
fieldtype: 'Link',
|
||||
target: 'NumberSeries',
|
||||
required: 1,
|
||||
default: 'PAY',
|
||||
},
|
||||
],
|
||||
fields: [],
|
||||
};
|
||||
|
@ -1,4 +1,5 @@
|
||||
import { t } from 'frappe';
|
||||
import { DEFAULT_NUMBER_SERIES } from '../../../frappe/utils/consts';
|
||||
import InvoiceTemplate from '../SalesInvoice/InvoiceTemplate.vue';
|
||||
import { getActions } from '../Transaction/Transaction';
|
||||
import PurchaseInvoice from './PurchaseInvoiceDocument';
|
||||
@ -134,6 +135,17 @@ export default {
|
||||
default: 0,
|
||||
readOnly: 1,
|
||||
},
|
||||
{
|
||||
fieldname: 'numberSeries',
|
||||
label: t`Number Series`,
|
||||
fieldtype: 'Link',
|
||||
target: 'NumberSeries',
|
||||
required: 1,
|
||||
getFilters: () => {
|
||||
return { referenceType: 'PurchaseInvoice' };
|
||||
},
|
||||
default: DEFAULT_NUMBER_SERIES['PurchaseInvoice'],
|
||||
},
|
||||
],
|
||||
|
||||
actions: getActions('PurchaseInvoice'),
|
||||
|
@ -6,14 +6,5 @@ export default {
|
||||
isSingle: 1,
|
||||
isChild: 0,
|
||||
keywordFields: [],
|
||||
fields: [
|
||||
{
|
||||
fieldname: 'numberSeries',
|
||||
label: t`Number Series`,
|
||||
fieldtype: 'Link',
|
||||
target: 'NumberSeries',
|
||||
required: 1,
|
||||
default: 'PINV',
|
||||
},
|
||||
],
|
||||
fields: [],
|
||||
};
|
||||
|
@ -1,5 +1,6 @@
|
||||
import { t } from 'frappe';
|
||||
import model from 'frappe/model';
|
||||
import { DEFAULT_NUMBER_SERIES } from '../../../frappe/utils/consts';
|
||||
import PurchaseInvoice from '../PurchaseInvoice/PurchaseInvoice';
|
||||
|
||||
export default model.extend(
|
||||
@ -13,6 +14,17 @@ export default model.extend(
|
||||
fieldname: 'items',
|
||||
childtype: 'PurchaseOrderItem',
|
||||
},
|
||||
{
|
||||
fieldname: 'numberSeries',
|
||||
label: t`Number Series`,
|
||||
fieldtype: 'Link',
|
||||
target: 'NumberSeries',
|
||||
required: 1,
|
||||
getFilters: () => {
|
||||
return { referenceType: 'PurchaseOrder' };
|
||||
},
|
||||
default: DEFAULT_NUMBER_SERIES['PurchaseOrder'],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
|
@ -5,10 +5,5 @@ import PurchaseInvoiceSettings from '../PurchaseInvoiceSettings/PurchaseInvoiceS
|
||||
export default model.extend(PurchaseInvoiceSettings, {
|
||||
name: 'PurchaseOrderSettings',
|
||||
label: t`Purchase Order Settings`,
|
||||
fields: [
|
||||
{
|
||||
fieldname: 'numberSeries',
|
||||
default: 'PO',
|
||||
},
|
||||
],
|
||||
fields: [],
|
||||
});
|
||||
|
@ -1,5 +1,6 @@
|
||||
import { t } from 'frappe';
|
||||
import model from 'frappe/model';
|
||||
import { DEFAULT_NUMBER_SERIES } from '../../../frappe/utils/consts';
|
||||
import PurchaseOrder from '../PurchaseOrder/PurchaseOrder';
|
||||
|
||||
export default model.extend(PurchaseOrder, {
|
||||
@ -11,5 +12,16 @@ export default model.extend(PurchaseOrder, {
|
||||
fieldname: 'items',
|
||||
childtype: 'PurchaseReceiptItem',
|
||||
},
|
||||
{
|
||||
fieldname: 'numberSeries',
|
||||
label: t`Number Series`,
|
||||
fieldtype: 'Link',
|
||||
target: 'NumberSeries',
|
||||
required: 1,
|
||||
getFilters: () => {
|
||||
return { referenceType: 'PurchaseReceipt' };
|
||||
},
|
||||
default: DEFAULT_NUMBER_SERIES['PurchaseReceipt'],
|
||||
},
|
||||
],
|
||||
});
|
||||
|
@ -5,10 +5,5 @@ import PurchaseOrderSettings from '../PurchaseOrderSettings/PurchaseOrderSetting
|
||||
export default model.extend(PurchaseOrderSettings, {
|
||||
name: 'PurchaseReceiptSettings',
|
||||
label: t`Purchase Receipt Settings`,
|
||||
fields: [
|
||||
{
|
||||
fieldname: 'numberSeries',
|
||||
default: 'PREC',
|
||||
},
|
||||
],
|
||||
fields: [],
|
||||
});
|
||||
|
@ -1,5 +1,6 @@
|
||||
import { t } from 'frappe';
|
||||
import model from 'frappe/model';
|
||||
import { DEFAULT_NUMBER_SERIES } from '../../../frappe/utils/consts';
|
||||
import SalesInvoice from '../SalesInvoice/SalesInvoice';
|
||||
|
||||
const Quotation = model.extend(
|
||||
@ -13,6 +14,17 @@ const Quotation = model.extend(
|
||||
fieldname: 'items',
|
||||
childtype: 'QuotationItem',
|
||||
},
|
||||
{
|
||||
fieldname: 'numberSeries',
|
||||
label: t`Number Series`,
|
||||
fieldtype: 'Link',
|
||||
target: 'NumberSeries',
|
||||
required: 1,
|
||||
getFilters: () => {
|
||||
return { referenceType: 'Quotation' };
|
||||
},
|
||||
default: DEFAULT_NUMBER_SERIES['Quotation'],
|
||||
},
|
||||
],
|
||||
links: [],
|
||||
},
|
||||
|
@ -5,10 +5,5 @@ import SalesInvoiceSettings from '../SalesInvoiceSettings/SalesInvoiceSettings';
|
||||
export default model.extend(SalesInvoiceSettings, {
|
||||
name: 'QuotationSettings',
|
||||
label: t`Quotation Settings`,
|
||||
fields: [
|
||||
{
|
||||
fieldname: 'numberSeries',
|
||||
default: 'QTN',
|
||||
},
|
||||
],
|
||||
fields: [],
|
||||
});
|
||||
|
@ -1,4 +1,5 @@
|
||||
import { t } from 'frappe';
|
||||
import { DEFAULT_NUMBER_SERIES } from '../../../frappe/utils/consts';
|
||||
import { getActions } from '../Transaction/Transaction';
|
||||
import InvoiceTemplate from './InvoiceTemplate.vue';
|
||||
import SalesInvoice from './SalesInvoiceDocument';
|
||||
@ -134,6 +135,17 @@ export default {
|
||||
default: 0,
|
||||
readOnly: 1,
|
||||
},
|
||||
{
|
||||
fieldname: 'numberSeries',
|
||||
label: t`Number Series`,
|
||||
fieldtype: 'Link',
|
||||
target: 'NumberSeries',
|
||||
required: 1,
|
||||
getFilters: () => {
|
||||
return { referenceType: 'SalesInvoice' };
|
||||
},
|
||||
default: DEFAULT_NUMBER_SERIES['SalesInvoice'],
|
||||
},
|
||||
],
|
||||
|
||||
actions: getActions('SalesInvoice'),
|
||||
|
@ -7,14 +7,6 @@ export default {
|
||||
isChild: 0,
|
||||
keywordFields: [],
|
||||
fields: [
|
||||
{
|
||||
fieldname: 'numberSeries',
|
||||
label: t`Number Series`,
|
||||
fieldtype: 'Link',
|
||||
target: 'NumberSeries',
|
||||
required: 1,
|
||||
default: 'SINV',
|
||||
},
|
||||
{
|
||||
fieldname: 'template',
|
||||
label: t`Template`,
|
||||
|
@ -1,5 +1,6 @@
|
||||
import { t } from 'frappe';
|
||||
import model from 'frappe/model';
|
||||
import { DEFAULT_NUMBER_SERIES } from '../../../frappe/utils/consts';
|
||||
import Quotation from '../Quotation/Quotation';
|
||||
|
||||
export default model.extend(Quotation, {
|
||||
@ -11,5 +12,16 @@ export default model.extend(Quotation, {
|
||||
fieldname: 'items',
|
||||
childtype: 'SalesOrderItem',
|
||||
},
|
||||
{
|
||||
fieldname: 'numberSeries',
|
||||
label: t`Number Series`,
|
||||
fieldtype: 'Link',
|
||||
target: 'NumberSeries',
|
||||
required: 1,
|
||||
getFilters: () => {
|
||||
return { referenceType: 'SalesOrder' };
|
||||
},
|
||||
default: DEFAULT_NUMBER_SERIES['SalesOrder'],
|
||||
},
|
||||
],
|
||||
});
|
||||
|
@ -5,10 +5,5 @@ import QuotationSettings from '../QuotationSettings/QuotationSettings';
|
||||
export default model.extend(QuotationSettings, {
|
||||
name: 'SalesOrderSettings',
|
||||
label: t`Sales Order Settings`,
|
||||
fields: [
|
||||
{
|
||||
fieldname: 'numberSeries',
|
||||
default: 'SO',
|
||||
},
|
||||
],
|
||||
fields: [],
|
||||
});
|
||||
|
20
patches/0.3.2/moveNumberSeriesFromSettings.js
Normal file
20
patches/0.3.2/moveNumberSeriesFromSettings.js
Normal file
@ -0,0 +1,20 @@
|
||||
import { invertMap } from '@/utils';
|
||||
import frappe from 'frappe';
|
||||
import { DEFAULT_NUMBER_SERIES } from 'frappe/utils/consts';
|
||||
|
||||
async function setReferencesOnNumberSeries() {
|
||||
const map = invertMap(DEFAULT_NUMBER_SERIES);
|
||||
const rows = await frappe.db.knex('NumberSeries');
|
||||
for (const row of rows) {
|
||||
if (row.referenceType === map[row.name]) {
|
||||
return;
|
||||
}
|
||||
|
||||
row.referenceType = map[row.name];
|
||||
}
|
||||
await frappe.db.prestigeTheTable('NumberSeries', rows);
|
||||
}
|
||||
|
||||
export default async function execute() {
|
||||
await setReferencesOnNumberSeries();
|
||||
}
|
@ -8,5 +8,10 @@
|
||||
"version": "0.0.4",
|
||||
"fileName": "convertCurrencyToStrings",
|
||||
"beforeMigrate": true
|
||||
},
|
||||
{
|
||||
"version": "0.3.2",
|
||||
"fileName": "moveNumberSeriesFromSettings",
|
||||
"beforeMigrate": false
|
||||
}
|
||||
]
|
||||
|
@ -20,15 +20,15 @@ export default async function postStart() {
|
||||
frappe.metaCache = {};
|
||||
|
||||
// init naming series if missing
|
||||
await naming.createNumberSeries('SINV-', 'SalesInvoiceSettings');
|
||||
await naming.createNumberSeries('PINV-', 'PurchaseInvoiceSettings');
|
||||
await naming.createNumberSeries('PAY-', 'PaymentSettings');
|
||||
await naming.createNumberSeries('JV-', 'JournalEntrySettings');
|
||||
await naming.createNumberSeries('QTN-', 'QuotationSettings');
|
||||
await naming.createNumberSeries('SO-', 'SalesOrderSettings');
|
||||
await naming.createNumberSeries('OF-', 'FulfillmentSettings');
|
||||
await naming.createNumberSeries('PO-', 'PurchaseOrderSettings');
|
||||
await naming.createNumberSeries('PREC-', 'PurchaseReceiptSettings');
|
||||
await naming.createNumberSeries('SINV-', 'SalesInvoice');
|
||||
await naming.createNumberSeries('PINV-', 'PurchaseInvoice');
|
||||
await naming.createNumberSeries('PAY-', 'Payment');
|
||||
await naming.createNumberSeries('JV-', 'JournalEntry');
|
||||
// await naming.createNumberSeries('QTN-', 'QuotationSettings');
|
||||
// await naming.createNumberSeries('SO-', 'SalesOrderSettings');
|
||||
// await naming.createNumberSeries('OF-', 'FulfillmentSettings');
|
||||
// await naming.createNumberSeries('PO-', 'PurchaseOrderSettings');
|
||||
// await naming.createNumberSeries('PREC-', 'PurchaseReceiptSettings');
|
||||
|
||||
// fetch singles
|
||||
// so that they are available synchronously
|
||||
|
@ -1,10 +1,9 @@
|
||||
<script>
|
||||
import frappe from 'frappe';
|
||||
import AutoComplete from './AutoComplete';
|
||||
import Badge from '@/components/Badge';
|
||||
import { openQuickEdit } from '@/utils';
|
||||
import frappe, { t } from 'frappe';
|
||||
import { markRaw } from 'vue';
|
||||
import { t } from 'frappe';
|
||||
import AutoComplete from './AutoComplete';
|
||||
|
||||
export default {
|
||||
name: 'Link',
|
||||
@ -84,12 +83,20 @@ export default {
|
||||
};
|
||||
},
|
||||
async getFilters(keyword) {
|
||||
if (this.doc) {
|
||||
return this.df.getFilters
|
||||
? (await this.df.getFilters(keyword, this.doc)) || {}
|
||||
: {};
|
||||
const { getFilters } = this.df;
|
||||
if (!getFilters) {
|
||||
return {};
|
||||
}
|
||||
|
||||
if (this.doc) {
|
||||
return (await getFilters(keyword, this.doc)) ?? {};
|
||||
}
|
||||
|
||||
try {
|
||||
return (await getFilters()) ?? {};
|
||||
} catch {
|
||||
return {};
|
||||
}
|
||||
return {};
|
||||
},
|
||||
getTarget() {
|
||||
return this.df.target;
|
||||
|
@ -103,6 +103,14 @@
|
||||
@change="(value) => doc.set('date', value)"
|
||||
:read-only="doc.submitted"
|
||||
/>
|
||||
<FormControl
|
||||
class="mt-2 text-base"
|
||||
input-class="bg-gray-100 px-3 py-2 text-base text-right"
|
||||
:df="meta.getField('numberSeries')"
|
||||
:value="doc.numberSeries"
|
||||
@change="(value) => doc.set('numberSeries', value)"
|
||||
:read-only="doc.submitted"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -190,20 +198,20 @@
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import frappe from 'frappe';
|
||||
import StatusBadge from '@/components/StatusBadge';
|
||||
import PageHeader from '@/components/PageHeader';
|
||||
import BackLink from '@/components/BackLink';
|
||||
import Button from '@/components/Button';
|
||||
import FormControl from '@/components/Controls/FormControl';
|
||||
import DropdownWithActions from '@/components/DropdownWithActions';
|
||||
import BackLink from '@/components/BackLink';
|
||||
import PageHeader from '@/components/PageHeader';
|
||||
import StatusBadge from '@/components/StatusBadge';
|
||||
import {
|
||||
openSettings,
|
||||
getActionsForDocument,
|
||||
getInvoiceStatus,
|
||||
showMessageDialog,
|
||||
routeTo,
|
||||
getActionsForDocument,
|
||||
getInvoiceStatus,
|
||||
openSettings,
|
||||
routeTo,
|
||||
showMessageDialog
|
||||
} from '@/utils';
|
||||
import frappe from 'frappe';
|
||||
import { handleErrorWithDialog } from '../errorHandling';
|
||||
|
||||
export default {
|
||||
|
@ -35,7 +35,7 @@
|
||||
<h1 class="text-2xl font-semibold">
|
||||
{{ doc._notInserted ? t`New Journal Entry` : doc.name }}
|
||||
</h1>
|
||||
<div class="flex justify-between mt-2">
|
||||
<div class="flex justify-between mt-2 gap-2">
|
||||
<div class="w-1/3">
|
||||
<FormControl
|
||||
:df="meta.getField('entryType')"
|
||||
@ -78,6 +78,16 @@
|
||||
:class="doc.submitted && 'pointer-events-none'"
|
||||
/>
|
||||
</div>
|
||||
<div class="w-1/3">
|
||||
<FormControl
|
||||
:df="meta.getField('numberSeries')"
|
||||
:value="doc.numberSeries"
|
||||
@change="(value) => doc.set('numberSeries', value)"
|
||||
input-class="bg-gray-100 p-2 text-base"
|
||||
:read-only="doc.submitted"
|
||||
:class="doc.submitted && 'pointer-events-none'"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mt-2 px-6 text-base">
|
||||
@ -118,14 +128,14 @@
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import frappe from 'frappe';
|
||||
import PageHeader from '@/components/PageHeader';
|
||||
import Button from '@/components/Button';
|
||||
import DropdownWithActions from '@/components/DropdownWithActions';
|
||||
import FormControl from '@/components/Controls/FormControl';
|
||||
import BackLink from '@/components/BackLink';
|
||||
import Button from '@/components/Button';
|
||||
import FormControl from '@/components/Controls/FormControl';
|
||||
import DropdownWithActions from '@/components/DropdownWithActions';
|
||||
import PageHeader from '@/components/PageHeader';
|
||||
import StatusBadge from '@/components/StatusBadge';
|
||||
import { showMessageDialog, getActionsForDocument, routeTo } from '@/utils';
|
||||
import { getActionsForDocument, routeTo, showMessageDialog } from '@/utils';
|
||||
import frappe from 'frappe';
|
||||
import { handleErrorWithDialog } from '../errorHandling';
|
||||
|
||||
export default {
|
||||
|
20
src/utils.js
20
src/utils.js
@ -536,3 +536,23 @@ export function getCOAList() {
|
||||
}
|
||||
return frappe.temp.coaList;
|
||||
}
|
||||
|
||||
export function invertMap(map) {
|
||||
const keys = Object.keys(map);
|
||||
const inverted = {};
|
||||
for (const key of keys) {
|
||||
const val = map[key];
|
||||
inverted[val] = key;
|
||||
}
|
||||
|
||||
return inverted;
|
||||
}
|
||||
|
||||
export function getPaddedName(prefix, next, padZeros) {
|
||||
const padding = padZeros ?? 4;
|
||||
|
||||
const l = next.toString().length;
|
||||
const z = '0'.repeat(Math.max(0, padding - l));
|
||||
|
||||
return prefix + z + next;
|
||||
}
|
||||
|
@ -12,20 +12,11 @@
|
||||
"allowSyntheticDefaultImports": true,
|
||||
"sourceMap": true,
|
||||
"baseUrl": ".",
|
||||
"types": [
|
||||
"webpack-env"
|
||||
],
|
||||
"types": ["webpack-env"],
|
||||
"paths": {
|
||||
"@/*": [
|
||||
"src/*"
|
||||
]
|
||||
"@/*": ["src/*"]
|
||||
},
|
||||
"lib": [
|
||||
"esnext",
|
||||
"dom",
|
||||
"dom.iterable",
|
||||
"scripthost"
|
||||
]
|
||||
"lib": ["esnext", "dom", "dom.iterable", "scripthost"]
|
||||
},
|
||||
"include": [
|
||||
"src/**/*.ts",
|
||||
@ -38,11 +29,10 @@
|
||||
"frappe/**/*.ts",
|
||||
"models/**/*.ts",
|
||||
"patches/**/*.ts",
|
||||
"patches/**/*.js",
|
||||
"reports/**/*.ts",
|
||||
"accounting/**/*.ts",
|
||||
"accounting/**/*.ts",
|
||||
"accounting/**/*.ts"
|
||||
],
|
||||
"exclude": [
|
||||
"node_modules"
|
||||
]
|
||||
"exclude": ["node_modules"]
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user