Compare commits

...

7 Commits

Author SHA1 Message Date
Ahmed Bouhuolia
6cb9d6da59 fix: Add publish manual journal from details drawer 2024-08-21 21:38:08 +02:00
Ahmed Bouhuolia
f46cd28f87 Merge pull request #618 from bigcapitalhq/display-details-bank-account
fix: Some bank account details hidden
2024-08-21 21:22:15 +02:00
Ahmed Bouhuolia
dffcfe50aa fix: some bank account details hidden 2024-08-21 21:19:59 +02:00
Ahmed Bouhuolia
fac55efbc7 Merge pull request #617 from bigcapitalhq/fix-impoort-itemns
fix: Cannot import items income and cost accounts
2024-08-21 19:33:50 +02:00
Ahmed Bouhuolia
8b90ce5f6c fix: cannot import items income and cost accounts 2024-08-21 19:32:59 +02:00
Ahmed Bouhuolia
b768f18294 chore: change subscription prices 2024-08-19 13:08:09 +02:00
Ahmed Bouhuolia
25297bc191 chore: dump CHANGELOG 2024-08-18 20:56:10 +02:00
13 changed files with 160 additions and 23 deletions

View File

@@ -2,6 +2,27 @@
All notable changes to Bigcapital server-side will be in this file. All notable changes to Bigcapital server-side will be in this file.
## [0.19.4] - 18-08-2024
* fix: Allow multi-lines to statements transactions by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/594
* feat: Add amount comparators to amount bank rule field by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/595
* fix: Transaction type and description do not show in general ledger. by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/596
* fix: Refresh accounts and account transactions. by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/597
* fix: Typo payments made by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/598
* fix: Typo categories list by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/600
* fix: Autofill the quick created customer/vendor by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/601
* fix: Remove views tabs from receipts list by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/602
* fix: Typo payment receive messages by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/599
* fix: Enhance Dropzone visual of accept and reject modes by @Champetaman in https://github.com/bigcapitalhq/bigcapital/pull/603
* fix: Matching bank transactions should create associate payment transactions by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/606
* fix: Change Dropzone title and subtitle by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/607
* fix: Inconsistance page size of paginated data tables by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/604
* fix: Database connection lost error by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/611
* fix: Language typos by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/613
* Fix: Correctly display Date, Published At, and Created At in ExpenseDrawerHeader by @Champetaman in https://github.com/bigcapitalhq/bigcapital/pull/612
* fix: Delete bank account with uncategorized transactions by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/614
* feat: activate/inactivate account from drawer details by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/615
## [v0.18.0] - 10-08-2024 ## [v0.18.0] - 10-08-2024
* feat: Bank rules for automated categorization by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/511 * feat: Bank rules for automated categorization by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/511

View File

@@ -164,6 +164,10 @@ export class Transformer {
return date ? moment(date).format(this.dateFormat) : ''; return date ? moment(date).format(this.dateFormat) : '';
} }
protected formatDateFromNow(date){
return date ? moment(date).fromNow(true) : '';
}
/** /**
* *
* @param number * @param number

View File

@@ -257,25 +257,25 @@ export default {
name: 'item.field.sell_price', name: 'item.field.sell_price',
fieldType: 'number', fieldType: 'number',
}, },
cost_price: { costPrice: {
name: 'item.field.cost_price', name: 'item.field.cost_price',
fieldType: 'number', fieldType: 'number',
}, },
costAccount: { costAccountId: {
name: 'item.field.cost_account', name: 'item.field.cost_account',
fieldType: 'relation', fieldType: 'relation',
relationModel: 'Account', relationModel: 'Account',
relationImportMatch: ['name', 'code'], relationImportMatch: ['name', 'code'],
importHint: 'Matches the account name or code.', importHint: 'Matches the account name or code.',
}, },
sellAccount: { sellAccountId: {
name: 'item.field.sell_account', name: 'item.field.sell_account',
fieldType: 'relation', fieldType: 'relation',
relationModel: 'Account', relationModel: 'Account',
relationImportMatch: ['name', 'code'], relationImportMatch: ['name', 'code'],
importHint: 'Matches the account name or code.', importHint: 'Matches the account name or code.',
}, },
inventoryAccount: { inventoryAccountId: {
name: 'item.field.inventory_account', name: 'item.field.inventory_account',
fieldType: 'relation', fieldType: 'relation',
relationModel: 'Account', relationModel: 'Account',

View File

@@ -8,7 +8,12 @@ export class CashflowAccountTransformer extends Transformer {
* @returns {string[]} * @returns {string[]}
*/ */
public includeAttributes = (): string[] => { public includeAttributes = (): string[] => {
return ['formattedAmount']; return [
'formattedAmount',
'lastFeedsUpdatedAt',
'lastFeedsUpdatedAtFormatted',
'lastFeedsUpdatedFromNow',
];
}; };
/** /**
@@ -37,4 +42,22 @@ export class CashflowAccountTransformer extends Transformer {
currencyCode: account.currencyCode, currencyCode: account.currencyCode,
}); });
}; };
/**
* Retrieves the last feeds update at formatted date.
* @param {IAccount} account
* @returns {string}
*/
protected lastFeedsUpdatedAtFormatted(account: IAccount): string {
return this.formatDate(account.lastFeedsUpdatedAt);
}
/**
* Retrieves the last feeds updated from now.
* @param {IAccount} account
* @returns {string}
*/
protected lastFeedsUpdatedFromNow(account: IAccount): string {
return this.formatDateFromNow(account.lastFeedsUpdatedAt);
}
} }

View File

@@ -43,12 +43,22 @@ export class CreateItem {
itemDTO.sellAccountId itemDTO.sellAccountId
); );
} }
// Validate the income account id existance if the item is sellable.
this.validators.validateIncomeAccountExistance(
itemDTO.sellable,
itemDTO.sellAccountId
);
if (itemDTO.costAccountId) { if (itemDTO.costAccountId) {
await this.validators.validateItemCostAccountExistance( await this.validators.validateItemCostAccountExistance(
tenantId, tenantId,
itemDTO.costAccountId itemDTO.costAccountId
); );
} }
// Validate the cost account id existance if the item is purchasable.
this.validators.validateCostAccountExistance(
itemDTO.purchasable,
itemDTO.costAccountId
);
if (itemDTO.inventoryAccountId) { if (itemDTO.inventoryAccountId) {
await this.validators.validateItemInventoryAccountExistance( await this.validators.validateItemInventoryAccountExistance(
tenantId, tenantId,

View File

@@ -55,6 +55,11 @@ export class EditItem {
itemDTO.categoryId itemDTO.categoryId
); );
} }
// Validate the income account id existance if the item is sellable.
this.validators.validateIncomeAccountExistance(
itemDTO.sellable,
itemDTO.sellAccountId
);
// Validate the sell account existance on the storage. // Validate the sell account existance on the storage.
if (itemDTO.sellAccountId) { if (itemDTO.sellAccountId) {
await this.validators.validateItemSellAccountExistance( await this.validators.validateItemSellAccountExistance(
@@ -62,6 +67,11 @@ export class EditItem {
itemDTO.sellAccountId itemDTO.sellAccountId
); );
} }
// Validate the cost account id existance if the item is purchasable.
this.validators.validateCostAccountExistance(
itemDTO.purchasable,
itemDTO.costAccountId
);
// Validate the cost account existance on the storage. // Validate the cost account existance on the storage.
if (itemDTO.costAccountId) { if (itemDTO.costAccountId) {
await this.validators.validateItemCostAccountExistance( await this.validators.validateItemCostAccountExistance(

View File

@@ -85,6 +85,42 @@ export class ItemsValidators {
} }
} }
/**
* Validates income account existance.
* @param {number|null} sellable - Detarmines if the item sellable.
* @param {number|null} incomeAccountId - Income account id.
* @throws {ServiceError(ERRORS.INCOME_ACCOUNT_REQUIRED_WITH_SELLABLE_ITEM)}
*/
public validateIncomeAccountExistance(
sellable?: boolean,
incomeAccountId?: number
) {
if (sellable && !incomeAccountId) {
throw new ServiceError(
ERRORS.INCOME_ACCOUNT_REQUIRED_WITH_SELLABLE_ITEM,
'Income account is require with sellable item.'
);
}
}
/**
* Validates the cost account existance.
* @param {boolean|null} purchasable - Detarmines if the item purchasble.
* @param {number|null} costAccountId - Cost account id.
* @throws {ServiceError(ERRORS.COST_ACCOUNT_REQUIRED_WITH_PURCHASABLE_ITEM)}
*/
public validateCostAccountExistance(
purchasable: boolean,
costAccountId?: number
) {
if (purchasable && !costAccountId) {
throw new ServiceError(
ERRORS.COST_ACCOUNT_REQUIRED_WITH_PURCHASABLE_ITEM,
'The cost account is required with purchasable item.'
);
}
}
/** /**
* Validate item inventory account existance and type. * Validate item inventory account existance and type.
* @param {number} tenantId * @param {number} tenantId

View File

@@ -26,6 +26,11 @@ export const ERRORS = {
PURCHASE_TAX_RATE_NOT_FOUND: 'PURCHASE_TAX_RATE_NOT_FOUND', PURCHASE_TAX_RATE_NOT_FOUND: 'PURCHASE_TAX_RATE_NOT_FOUND',
SELL_TAX_RATE_NOT_FOUND: 'SELL_TAX_RATE_NOT_FOUND', SELL_TAX_RATE_NOT_FOUND: 'SELL_TAX_RATE_NOT_FOUND',
INCOME_ACCOUNT_REQUIRED_WITH_SELLABLE_ITEM:
'INCOME_ACCOUNT_REQUIRED_WITH_SELLABLE_ITEM',
COST_ACCOUNT_REQUIRED_WITH_PURCHASABLE_ITEM:
'COST_ACCOUNT_REQUIRED_WITH_PURCHASABLE_ITEM',
}; };
export const DEFAULT_VIEW_COLUMNS = []; export const DEFAULT_VIEW_COLUMNS = [];

View File

@@ -62,6 +62,7 @@ export function BankAccount({
balance, balance,
loading = false, loading = false,
updatedBeforeText, updatedBeforeText,
uncategorizedTransactionsCount,
...restProps ...restProps
}) { }) {
return ( return (
@@ -77,17 +78,19 @@ export function BankAccount({
</BankAccountHeader> </BankAccountHeader>
<BankAccountMeta> <BankAccountMeta>
{false && ( {uncategorizedTransactionsCount > 0 && (
<BankAccountMetaLine <BankAccountMetaLine
title={intl.get('cash_flow.transactions_for_review')} title={intl.get('cash_flow.transactions_for_review')}
value={'0'} value={uncategorizedTransactionsCount}
className={clsx({ [Classes.SKELETON]: loading })} className={clsx({ [Classes.SKELETON]: loading })}
/> />
)} )}
{updatedBeforeText && (
<BankAccountMetaLine <BankAccountMetaLine
title={updatedBeforeText} title={updatedBeforeText}
className={clsx({ [Classes.SKELETON]: loading })} className={clsx({ [Classes.SKELETON]: loading })}
/> />
)}
</BankAccountMeta> </BankAccountMeta>
<BankAccountBalance amount={balance} loading={loading} /> <BankAccountBalance amount={balance} loading={loading} />

View File

@@ -44,9 +44,9 @@ export const SubscriptionPlans = [
}, },
{ text: 'Unlimited User Seats' }, { text: 'Unlimited User Seats' },
], ],
monthlyPrice: '$10', monthlyPrice: '$20',
monthlyPriceLabel: 'Per month', monthlyPriceLabel: 'Per month',
annuallyPrice: '$7.5', annuallyPrice: '$15',
annuallyPriceLabel: 'Per month', annuallyPriceLabel: 'Per month',
monthlyVariantId: '446152', monthlyVariantId: '446152',
// monthlyVariantId: '450016', // monthlyVariantId: '450016',
@@ -78,9 +78,9 @@ export const SubscriptionPlans = [
{ text: 'Smart Financial Reports' }, { text: 'Smart Financial Reports' },
{ text: 'Advanced Inventory Reports' }, { text: 'Advanced Inventory Reports' },
], ],
monthlyPrice: '$20', monthlyPrice: '$40',
monthlyPriceLabel: 'Per month', monthlyPriceLabel: 'Per month',
annuallyPrice: '$15', annuallyPrice: '$30',
annuallyPriceLabel: 'Per month', annuallyPriceLabel: 'Per month',
// monthlyVariantId: '450028', // monthlyVariantId: '450028',
monthlyVariantId: '446155', monthlyVariantId: '446155',
@@ -101,9 +101,9 @@ export const SubscriptionPlans = [
}, },
{ text: 'Analysis Cost Center' }, { text: 'Analysis Cost Center' },
], ],
monthlyPrice: '$25', monthlyPrice: '$55',
monthlyPriceLabel: 'Per month', monthlyPriceLabel: 'Per month',
annuallyPrice: '$19', annuallyPrice: '$40',
annuallyPriceLabel: 'Per month', annuallyPriceLabel: 'Per month',
featured: true, featured: true,
// monthlyVariantId: '450031', // monthlyVariantId: '450031',
@@ -128,9 +128,9 @@ export const SubscriptionPlans = [
hint: 'Track the organization inventory in multiple warehouses and transfer goods between them.', hint: 'Track the organization inventory in multiple warehouses and transfer goods between them.',
}, },
], ],
monthlyPrice: '$40', monthlyPrice: '$60',
monthlyPriceLabel: 'Per month', monthlyPriceLabel: 'Per month',
annuallyPrice: '$30', annuallyPrice: '$45',
annuallyPriceLabel: 'Per month', annuallyPriceLabel: 'Per month',
// monthlyVariantId: '450024', // monthlyVariantId: '450024',
monthlyVariantId: '446167', monthlyVariantId: '446167',

View File

@@ -43,6 +43,7 @@ export function useExcludedTransactionsColumns() {
{ {
Header: 'Description', Header: 'Description',
accessor: descriptionAccessor, accessor: descriptionAccessor,
textOverview: true,
}, },
{ {
Header: 'Payee', Header: 'Payee',

View File

@@ -123,7 +123,12 @@ function CashflowBankAccount({
code={account.code} code={account.code}
balance={!isNull(account.amount) ? account.formatted_amount : '-'} balance={!isNull(account.amount) ? account.formatted_amount : '-'}
type={account.account_type} type={account.account_type}
updatedBeforeText={getUpdatedBeforeText(account.createdAt)} updatedBeforeText={
account.last_feeds_updated_from_now
? `Updated ${account.last_feeds_updated_from_now} ago`
: ''
}
uncategorizedTransactionsCount={account.uncategorized_transactions}
/> />
</CashflowAccountAnchor> </CashflowAccountAnchor>
</ContextMenu2> </ContextMenu2>

View File

@@ -13,6 +13,7 @@ import {
DrawerActionsBar, DrawerActionsBar,
Can, Can,
FormattedMessage as T, FormattedMessage as T,
If,
} from '@/components'; } from '@/components';
import withAlertsActions from '@/containers/Alert/withAlertActions'; import withAlertsActions from '@/containers/Alert/withAlertActions';
@@ -35,7 +36,7 @@ function ManualJournalDrawerActionBar({
closeDrawer, closeDrawer,
}) { }) {
const history = useHistory(); const history = useHistory();
const { manualJournalId } = useManualJournalDrawerContext(); const { manualJournalId, manualJournal } = useManualJournalDrawerContext();
// Handle edit manual journal action. // Handle edit manual journal action.
const handleEditManualJournal = () => { const handleEditManualJournal = () => {
@@ -48,6 +49,11 @@ function ManualJournalDrawerActionBar({
openAlert('journal-delete', { manualJournalId }); openAlert('journal-delete', { manualJournalId });
}; };
// Handle manual journal publish action.
const handlePublishManualJournal = () => {
openAlert('journal-publish', { manualJournalId });
};
return ( return (
<DrawerActionsBar> <DrawerActionsBar>
<NavbarGroup> <NavbarGroup>
@@ -59,6 +65,19 @@ function ManualJournalDrawerActionBar({
onClick={handleEditManualJournal} onClick={handleEditManualJournal}
/> />
</Can> </Can>
<If condition={!manualJournal.is_published}>
<Can I={ManualJournalAction.Edit} a={AbilitySubject.ManualJournal}>
<NavbarDivider />
<Button
className={Classes.MINIMAL}
icon={<Icon icon="arrow-to-top" />}
text={'Publish'}
intent={Intent.SUCCESS}
onClick={handlePublishManualJournal}
/>
</Can>
</If>
<Can I={ManualJournalAction.Delete} a={AbilitySubject.ManualJournal}> <Can I={ManualJournalAction.Delete} a={AbilitySubject.ManualJournal}>
<NavbarDivider /> <NavbarDivider />
<Button <Button