2
0
mirror of https://github.com/frappe/books.git synced 2024-11-10 07:40:55 +00:00

Merge branch 'master' into fix/profit-loss-report-filter-fields

This commit is contained in:
Piyush Singhania 2022-01-13 13:52:38 +05:30 committed by GitHub
commit 23e633318c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
19 changed files with 234 additions and 58 deletions

View File

@ -42,7 +42,7 @@ jobs:
- name: Setup Books - name: Setup Books
run: | run: |
cd $GITHUB_WORKSPACE/main cd $GITHUB_WORKSPACE/main
yarn yarn upgrade frappejs
yarn link frappejs yarn link frappejs
- name: Install RPM - name: Install RPM

View File

@ -34,7 +34,7 @@ jobs:
- name: Setup Books - name: Setup Books
run: | run: |
cd $GITHUB_WORKSPACE/main cd $GITHUB_WORKSPACE/main
yarn yarn upgrade frappejs
yarn link frappejs yarn link frappejs
- name: Run build - name: Run build
@ -51,6 +51,15 @@ jobs:
cd $GITHUB_WORKSPACE/main cd $GITHUB_WORKSPACE/main
yarn electron:build --mac --publish always yarn electron:build --mac --publish always
- name: Tar files
run: tar -cvf dist-macOS.tar $GITHUB_WORKSPACE/main/dist_electron
- name: Upload Artifacts
uses: actions/upload-artifact@v2
with:
name: dist-macOS
path: dist-macOS.tar
build-linux: build-linux:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
@ -79,7 +88,7 @@ jobs:
- name: Setup Books - name: Setup Books
run: | run: |
cd $GITHUB_WORKSPACE/main cd $GITHUB_WORKSPACE/main
yarn yarn upgrade frappejs
yarn link frappejs yarn link frappejs
- name: Run build - name: Run build
@ -89,6 +98,15 @@ jobs:
cd $GITHUB_WORKSPACE/main cd $GITHUB_WORKSPACE/main
yarn electron:build --linux --publish always yarn electron:build --linux --publish always
- name: Tar files
run: tar -cvf dist-linux.tar $GITHUB_WORKSPACE/main/dist_electron
- name: Upload Artifacts
uses: actions/upload-artifact@v2
with:
name: dist-linux
path: dist-linux.tar
build-windows: build-windows:
runs-on: windows-2022 runs-on: windows-2022
defaults: defaults:
@ -121,7 +139,7 @@ jobs:
- name: Setup Books - name: Setup Books
run: | run: |
cd $GITHUB_WORKSPACE/main cd $GITHUB_WORKSPACE/main
yarn yarn upgrade frappejs
yarn link frappejs yarn link frappejs
- name: Run build - name: Run build
@ -132,3 +150,12 @@ jobs:
run: | run: |
cd $GITHUB_WORKSPACE/main cd $GITHUB_WORKSPACE/main
yarn electron:build --win --publish always yarn electron:build --win --publish always
- name: Tar files
run: tar -cvf dist-windows.tar $GITHUB_WORKSPACE/main/dist_electron
- name: Upload Artifacts
uses: actions/upload-artifact@v2
with:
name: dist-windows
path: dist-windows.tar

View File

@ -2,7 +2,7 @@ import { showMessageDialog } from '@/utils';
import frappe from 'frappejs'; import frappe from 'frappejs';
import { _ } from 'frappejs/utils'; import { _ } from 'frappejs/utils';
import { DateTime } from 'luxon'; import { DateTime } from 'luxon';
import { saveExportData } from '../reports/commonExporter'; import { saveExportData, exportCsv } from '../reports/commonExporter';
import { getSavePath } from '../src/utils'; import { getSavePath } from '../src/utils';
// prettier-ignore // prettier-ignore
@ -252,3 +252,85 @@ async function generateB2csData(invoices) {
return b2cs; return b2cs;
} }
export async function generateGstr2Csv(getReportData) {
const { gstin } = frappe.AccountingSettings;
if (!gstin) {
showMessageDialog({
message: _('Export Failed'),
description: _('Please set GSTIN in General Settings.'),
});
return;
}
const {
rows,
columns,
filters: { transferType, toDate },
} = getReportData();
const { filePath, canceled } = await getSavePath('gstr-2', 'csv');
if (canceled || !filePath) return;
let gstData;
if (transferType === 'B2B') {
gstData = await generateB2bCsvGstr2(rows, columns);
}
await exportCsv(gstData.rows, gstData.columns, filePath);
}
async function generateB2bCsvGstr2(rows, columns) {
const csvColumns = [
{
label: 'GSTIN of Supplier',
fieldname: 'gstin',
},
{
label: 'Invoice Number',
fieldname: 'invNo',
},
{
label: 'Invoice Date',
fieldname: 'invDate',
},
{
label: 'Invoice Value',
fieldname: 'invAmt',
},
{
label: 'Place of supply',
fieldname: 'place',
},
{
label: 'Reverse Charge',
fieldname: 'reverseCharge',
},
{
label: 'Rate',
fieldname: 'rate',
},
{
label: 'Taxable Value',
fieldname: 'taxVal',
},
{
label: 'Intergrated Tax Paid',
fieldname: 'igstAmt',
},
{
label: 'Central Tax Paid',
fieldname: 'cgstAmt',
},
{
label: 'State/UT Tax Paid',
fieldname: 'sgstAmt',
},
]
return {
columns: csvColumns,
rows: rows,
}
}

View File

@ -50,6 +50,12 @@ export default {
label: 'State', label: 'State',
placeholder: 'State', placeholder: 'State',
fieldtype: 'AutoComplete', fieldtype: 'AutoComplete',
emptyMessage: (doc) => {
if (doc.country) {
return 'Enter State';
}
return 'Enter Country to load States';
},
getList: getStates, getList: getStates,
}, },
{ {

View File

@ -1,27 +1,11 @@
import { DateTime } from 'luxon'; import { DateTime } from 'luxon';
import { generateGstr1Json, stateCodeMap } from '../../accounting/gst'; import { stateCodeMap } from '../../accounting/gst';
import { titleCase } from '../../src/utils'; import { titleCase } from '../../src/utils';
const transferTypeMap = {
B2B: 'B2B',
B2CL: 'B2C-Large',
B2CS: 'B2C-Small',
NR: 'Nil Rated, Exempted and Non GST supplies',
};
const stateList = Object.keys(stateCodeMap).map(titleCase).sort(); const stateList = Object.keys(stateCodeMap).map(titleCase).sort();
export default { export default {
filterFields: [ filterFields: [
{
fieldtype: 'Select',
label: 'Transfer Type',
placeholder: 'Transfer Type',
fieldname: 'transferType',
options: Object.keys(transferTypeMap),
map: transferTypeMap,
default: 'B2B',
size: 'small',
},
{ {
fieldtype: 'AutoComplete', fieldtype: 'AutoComplete',
label: 'Place', label: 'Place',
@ -47,17 +31,6 @@ export default {
default: () => DateTime.local().toISODate(), default: () => DateTime.local().toISODate(),
}, },
], ],
actions: [
{
group: 'Export',
label: 'JSON',
type: 'primary',
action: async (report, filters) => {
generateGstr1Json(report, filters);
},
},
],
getColumns({ filters }) { getColumns({ filters }) {
const columns = [ const columns = [
{ {

View File

@ -1,10 +1,40 @@
const title = 'GSTR 1'; const title = 'GSTR 1';
import baseConfig from './BaseViewConfig'; import baseConfig from './BaseViewConfig';
import { generateGstr1Json } from '../../accounting/gst';
const transferTypeMap = {
B2B: 'B2B',
B2CL: 'B2C-Large',
B2CS: 'B2C-Small',
NR: 'Nil Rated, Exempted and Non GST supplies',
};
const transferType = {
fieldtype: 'Select',
label: 'Transfer Type',
placeholder: 'Transfer Type',
fieldname: 'transferType',
options: Object.keys(transferTypeMap),
map: transferTypeMap,
default: 'B2B',
size: 'small',
};
const actions = [
{
group: 'Export',
label: 'JSON',
type: 'primary',
action: async (report, filters) => {
generateGstr1Json(report, filters);
},
},
]
export default { export default {
title: title, title: title,
method: 'gstr-1', method: 'gstr-1',
filterFields: baseConfig.filterFields, filterFields: [ transferType, ...baseConfig.filterFields],
actions: baseConfig.actions, actions: actions,
getColumns: baseConfig.getColumns, getColumns: baseConfig.getColumns,
}; };

View File

@ -16,9 +16,6 @@ class GSTR2 extends BaseGSTR {
// prettier-ignore // prettier-ignore
const conditions = { const conditions = {
'B2B': row => row.gstin, 'B2B': row => row.gstin,
'B2CL': row => !row.gstin && !row.inState && row.invAmt >= 250000,
'B2CS': row =>
!row.gstin && (row.inState || (row.inState && row.invAmt < 250000))
}; };
if (!params.transferType) return data; if (!params.transferType) return data;

View File

@ -1,10 +1,37 @@
const title = 'GSTR 2'; const title = 'GSTR 2';
import baseConfig from './BaseViewConfig'; import baseConfig from './BaseViewConfig';
import { generateGstr2Csv } from '../../accounting/gst';
const transferTypeMap = {
B2B: 'B2B',
};
const transferType = {
fieldtype: 'Select',
label: 'Transfer Type',
placeholder: 'Transfer Type',
fieldname: 'transferType',
options: Object.keys(transferTypeMap),
map: transferTypeMap,
default: 'B2B',
size: 'small',
};
const actions = [
{
group: 'Export',
label: 'CSV',
type: 'primary',
action: async (report, filters) => {
generateGstr2Csv(report, filters);
},
},
]
export default { export default {
title: title, title: title,
method: 'gstr-2', method: 'gstr-2',
filterFields: baseConfig.filterFields, filterFields: [ transferType, ...baseConfig.filterFields],
actions: baseConfig.actions, actions: actions,
getColumns: baseConfig.getColumns, getColumns: baseConfig.getColumns,
}; };

View File

@ -34,7 +34,7 @@ function csvFormat(value) {
return value; return value;
} }
async function exportCsv(rows, columns, filePath) { export async function exportCsv(rows, columns, filePath) {
const fieldnames = columns.map(({ fieldname }) => fieldname); const fieldnames = columns.map(({ fieldname }) => fieldname);
const labels = columns.map(({ label }) => csvFormat(label)); const labels = columns.map(({ label }) => csvFormat(label));
const csvRows = [ const csvRows = [

View File

@ -1,5 +1,5 @@
<template> <template>
<Dropdown :items="suggestions" :is-loading="isLoading"> <Dropdown :items="suggestions" :is-loading="isLoading" :df="df" :doc="doc">
<template <template
v-slot="{ v-slot="{
toggleDropdown, toggleDropdown,

View File

@ -35,7 +35,7 @@
width="14" width="14"
height="14" height="14"
viewBox="0 0 14 14" viewBox="0 0 14 14"
fill="none" :fill="offColor"
xmlns="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg"
> >
<rect <rect
@ -44,7 +44,7 @@
width="13" width="13"
height="13" height="13"
rx="3.5" rx="3.5"
:stroke="color" :stroke="offBorderColor"
/> />
</svg> </svg>
@ -71,7 +71,11 @@ export default {
name: 'Check', name: 'Check',
extends: Base, extends: Base,
data() { data() {
return { color: '#A1ABB4' }; return {
offBorderColor: 'rgba(17, 43, 66, 0.201322)',
offColor: '#FFFFFF',
color: '#A1ABB4'
};
}, },
computed: { computed: {
inputClasses() { inputClasses() {

View File

@ -1,6 +1,6 @@
<template> <template>
<Popover @open="selectCurrentMonthYear"> <Popover @open="selectCurrentMonthYear">
<template v-slot:target="{ togglePopover }"> <template v-slot:target="{ togglePopover, handleBlur }">
<input <input
type="text" type="text"
:class="inputClass" :class="inputClass"
@ -8,6 +8,7 @@
:placeholder="placeholder" :placeholder="placeholder"
readonly readonly
@focus="!readonly ? togglePopover() : null" @focus="!readonly ? togglePopover() : null"
@blur="handleBlur"
/> />
</template> </template>
<template v-slot:content="{ togglePopover }"> <template v-slot:content="{ togglePopover }">

View File

@ -21,8 +21,11 @@
<div v-if="isLoading" class="p-2 text-gray-600 italic"> <div v-if="isLoading" class="p-2 text-gray-600 italic">
{{ _('Loading...') }} {{ _('Loading...') }}
</div> </div>
<div v-if="!isLoading && dropdownItems.length === 0" class="p-2 text-gray-600 italic"> <div
{{ _('Empty') }} v-if="!isLoading && dropdownItems.length === 0"
class="p-2 text-gray-600 italic"
>
{{ getEmptyMessage() }}
</div> </div>
<template v-else> <template v-else>
<div v-for="d in dropdownItems" :key="d.label"> <div v-for="d in dropdownItems" :key="d.label">
@ -92,6 +95,12 @@ export default {
type: Boolean, type: Boolean,
default: false, default: false,
}, },
df: {
default: null,
},
doc: {
default: null,
},
}, },
components: { components: {
Popover, Popover,
@ -156,6 +165,15 @@ export default {
}, },
}, },
methods: { methods: {
getEmptyMessage() {
const { emptyMessage } = this.df ?? {};
if (typeof emptyMessage === 'function') {
return _(emptyMessage(this.doc));
} else if (emptyMessage) {
return _(emptyMessage);
}
return _('Empty');
},
selectItem(d) { selectItem(d) {
if (d.action) { if (d.action) {
d.action(); d.action();

View File

@ -1,7 +1,11 @@
<template> <template>
<div ref="reference"> <div ref="reference">
<div class="h-full"> <div class="h-full">
<slot name="target" :togglePopover="togglePopover"></slot> <slot
name="target"
:togglePopover="togglePopover"
:handleBlur="handleBlur"
></slot>
</div> </div>
<div <div
ref="popover" ref="popover"
@ -125,6 +129,9 @@ export default {
this.isOpen = false; this.isOpen = false;
this.$emit('close'); this.$emit('close');
}, },
handleBlur({ relatedTarget }) {
relatedTarget && this.close();
},
}, },
}; };
</script> </script>

View File

@ -11,7 +11,6 @@
items-center items-center
mb-3 mb-3
w-60 w-60
bg-gray-100
" "
style="transition: opacity 150ms ease-in" style="transition: opacity 150ms ease-in"
:style="{ opacity }" :style="{ opacity }"

View File

@ -283,6 +283,9 @@ export default {
} }
switch (key) { switch (key) {
case 'Invoice':
await this.updateChecks({ invoiceSetup: 1 });
break;
case 'General': case 'General':
await this.updateChecks({ companySetup: 1 }); await this.updateChecks({ companySetup: 1 });
break; break;
@ -323,11 +326,6 @@ export default {
return; return;
} }
let printSettings = await frappe.getSingle('PrintSettings');
if (printSettings.logo && printSettings.address) {
toUpdate.invoiceSetup = 1;
}
if (!frappe.GetStarted.itemCreated) { if (!frappe.GetStarted.itemCreated) {
let { count } = ( let { count } = (
await frappe.db.knex('Item').count('name as count') await frappe.db.knex('Item').count('name as count')

View File

@ -22,12 +22,12 @@
class="w-40 ml-2 first:ml-0" class="w-40 ml-2 first:ml-0"
:class=" :class="
df.fieldtype === 'Check' && df.fieldtype === 'Check' &&
'flex justify-between items-center bg-gray-100 px-2 overflow-scroll rounded' 'flex justify-between items-center bg-gray-100 px-2 rounded'
" "
v-for="df in report.filterFields" v-for="df in report.filterFields"
:key="df.fieldname" :key="df.fieldname"
> >
<div v-if="df.fieldtype === 'Check'" class="text-sm"> <div v-if="df.fieldtype === 'Check'" class="text-sm mr-2">
{{ df.label }} {{ df.label }}
</div> </div>
<FormControl <FormControl

View File

@ -19,7 +19,9 @@ export default {
}; };
}, },
async mounted() { async mounted() {
this.doc = await frappe.getSingle('AccountingSettings'); this.doc = await frappe.getDoc('AccountingSettings', 'AccountingSettings', {
skipDocumentCache: true
});
}, },
computed: { computed: {
fields() { fields() {

View File

@ -99,6 +99,11 @@ const config = {
label: _('GSTR1'), label: _('GSTR1'),
route: '/report/gstr-1', route: '/report/gstr-1',
hidden: () => frappe.AccountingSettings.country !== 'India', hidden: () => frappe.AccountingSettings.country !== 'India',
},
{
label: _('GSTR2'),
route: '/report/gstr-2',
hidden: () => frappe.AccountingSettings.country !== 'India',
} }
], ],
}, },