Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 9 additions & 3 deletions docker-compose.prod.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,20 @@ services:

webapp:
container_name: bigcapital-webapp
image: bigcapitalhq/webapp:latest
build:
context: ./
dockerfile: packages/webapp/Dockerfile
#image: bigcapitalhq/webapp:latest
restart: on-failure
networks:
- bigcapital_network

server:
container_name: bigcapital-server
image: bigcapitalhq/server:latest
build:
context: ./
dockerfile: packages/server/Dockerfile
#image: bigcapitalhq/server:latest
expose:
- '3000'
links:
Expand Down Expand Up @@ -206,4 +212,4 @@ volumes:
# Networks
networks:
bigcapital_network:
driver: bridge
driver: bridge
2 changes: 2 additions & 0 deletions packages/server/resources/locales/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -283,6 +283,8 @@
"invoice.field.payment_amount": "Payment amount",
"invoice.field.due_amount": "Due amount",
"invoice.field.delivered": "Delivered",
"invoice.field.is_inclusive_tax": "Amounts Are",
"invoice.field.tax_rate": "Tax Rate",
"invoice.field.item_name": "Item Name",
"invoice.field.rate": "Rate",
"invoice.field.quantity": "Quantity",
Expand Down
13 changes: 12 additions & 1 deletion packages/server/src/models/SaleInvoice.Settings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ export default {
relationKey: 'customer',

relationEntityLabel: 'display_name',
relationEntityKey: 'id',
relationEntityKey: 'display_name',
},
invoice_date: {
name: 'invoice.field.invoice_date',
Expand Down Expand Up @@ -246,6 +246,11 @@ export default {
fieldType: 'text',
printable: false,
},
isInclusiveTax: {
name: 'invoice.field.is_inclusive_tax',
fieldType: 'boolean',
printable: false,
},
entries: {
name: 'invoice.field.entries',
fieldType: 'collection',
Expand All @@ -261,6 +266,12 @@ export default {
required: true,
importHint: 'Matches the item name or code.',
},
taxRateId: {
name: 'invoice.field.tax_rate',
fieldType: 'relation',
relationModel: 'TaxRate',
relationImportMatch: ['name', 'code'],
},
rate: {
name: 'invoice.field.rate',
fieldType: 'number',
Expand Down
6 changes: 3 additions & 3 deletions packages/server/src/models/TaxRate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,9 @@ export default class TaxRate extends mixin(TenantModel, [
/**
* Soft delete query builder.
*/
static get QueryBuilder() {
return SoftDeleteQueryBuilder;
}
// static get QueryBuilder() {
// return SoftDeleteQueryBuilder;
// }

/**
* Timestamps columns.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ export default class GeneralLedgerSheet extends R.compose(
this.query = query;
this.numberFormat = this.query.numberFormat;
this.repository = repository;
this.baseCurrency = this.repository.tenant.metadata.currencyCode;
this.baseCurrency = this.repository.tenant.metadata.baseCurrency;
this.i18n = i18n;
}

Expand Down
38 changes: 37 additions & 1 deletion packages/server/src/services/Import/ImportFileMapping.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,9 @@ import {
} from './interfaces';
import ResourceService from '../Resource/ResourceService';
import { ServiceError } from '@/exceptions';
import { ERRORS } from './_utils';
import { ERRORS,readImportFile } from './_utils';
import { Import } from '@/system/models';
import { parseSheetData } from './sheet_utils';

@Service()
export class ImportFileMapping {
Expand Down Expand Up @@ -40,6 +41,7 @@ export class ImportFileMapping {

// Validate the date format mapping.
this.validateDateFormatMapping(tenantId, importFile.resource, maps);
await this.validateDataForTax(tenantId, importFile);

const mappingStringified = JSON.stringify(maps);

Expand Down Expand Up @@ -74,11 +76,17 @@ export class ImportFileMapping {
importFile.columnsParsed.map((field) => [field, ''])
);
const invalid = [];
let isInclusiveThere = 0;


// is not empty, is not undefined or map.group
maps.forEach((map) => {
let _invalid = true;


if(map.to === 'taxRateId' || map.to === 'isInclusiveTax'){
isInclusiveThere = isInclusiveThere+1;
}
if (!map.group && fields[map.to]) {
_invalid = false;
}
Expand All @@ -95,6 +103,9 @@ export class ImportFileMapping {
if (invalid.length > 0) {
throw new ServiceError(ERRORS.INVALID_MAP_ATTRS);
}
else if(isInclusiveThere == 1) {
throw new ServiceError(ERRORS.AMOUNT_ARE_AND_TAX_RATE_ARE_REQUIRED_IF_ANY_ONE_OF_THEM_SELECTED);
}
}

/**
Expand Down Expand Up @@ -153,4 +164,29 @@ export class ImportFileMapping {
}
});
}
private async validateDataForTax(tenantId: number,
importFile: any,
)
{
const buffer = await readImportFile(importFile.filename);
const [sheetData, sheetColumns] = parseSheetData(buffer);
if(importFile.resource === "SaleInvoice")
{
let invoiceNo = "";
let isInvoiceTaxInclusive;
const Count = sheetData.length;
for (let i = 0; i < Count; i++) {
if (sheetData[i]['Amounts Are'])
{
invoiceNo = sheetData[i]['Invoice No.'];
isInvoiceTaxInclusive = sheetData[i]['Amounts Are'];
for (let j = i + 1; j < Count; j++) {
if (invoiceNo === sheetData[j]['Invoice No.'] && isInvoiceTaxInclusive !== sheetData[j]['Amounts Are']) {
throw new ServiceError(ERRORS.AN_INVOICE_CAN_HAVE_ONE_AMOUNT_IN_EITHER_TRUE_OR_FALSE);
}
}
}
}
}
}
}
3 changes: 3 additions & 0 deletions packages/server/src/services/Import/_utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,9 @@ export const ERRORS = {
INVALID_MAP_DATE_FORMAT: 'INVALID_MAP_DATE_FORMAT',
MAP_DATE_FORMAT_NOT_DEFINED: 'MAP_DATE_FORMAT_NOT_DEFINED',
IMPORTED_SHEET_EMPTY: 'IMPORTED_SHEET_EMPTY',
AMOUNT_ARE_AND_TAX_RATE_ARE_REQUIRED_IF_ANY_ONE_OF_THEM_SELECTED: 'AMOUNT_ARE_AND_TAX_RATE_ARE_REQUIRED_IF_ANY_ONE_OF_THEM_SELECTED',
AN_INVOICE_CAN_HAVE_ONE_AMOUNT_IN_EITHER_TRUE_OR_FALSE:"AN_INVOICE_CAN_HAVE_ONE_AMOUNT_IN_EITHER_TRUE_OR_FALSE",

};

/**
Expand Down
7 changes: 7 additions & 0 deletions packages/server/src/services/Sales/Invoices/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,8 @@ export const SaleInvoicesSampleData = [
Quantity: 100,
Rate: 100,
Description: 'Description',
'Amounts Are': 'True',
'Tax Rate': 'Tax18%'
},
{
'Invoice No.': 'B-102',
Expand All @@ -143,6 +145,9 @@ export const SaleInvoicesSampleData = [
Quantity: 200,
Rate: 50,
Description: 'Description',
'Amounts Are': 'True',
'Tax Rate': 'Tax18%'

},
{
'Invoice No.': 'B-103',
Expand All @@ -159,6 +164,8 @@ export const SaleInvoicesSampleData = [
Quantity: 100,
Rate: 100,
Description: 'Description',
'Amounts Are': 'True',
'Tax Rate': 'Tax18%'
},
];

Expand Down
12 changes: 12 additions & 0 deletions packages/webapp/src/containers/Import/ImportFileMappingForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,18 @@ export function ImportFileMappingForm({
intent: Intent.DANGER,
});
}
else if (data.errors.find((e) => e.type === 'AMOUNT_ARE_AND_TAX_RATE_ARE_REQUIRED_IF_ANY_ONE_OF_THEM_SELECTED')) {
AppToaster.show({
message: 'Amounts Are and Tax Rate are required if any one of them selected',
intent: Intent.DANGER,
});
}
else if (data.errors.find((e) => e.type === 'AN_INVOICE_CAN_HAVE_ONE_AMOUNT_IN_EITHER_TRUE_OR_FALSE')) {
AppToaster.show({
message: 'An Invoice can have same Amounts In either true or false',
intent: Intent.DANGER,
});
}
setSubmitting(false);
});
};
Expand Down