mirror of
https://github.com/bigcapitalhq/bigcapital.git
synced 2026-02-20 06:40:31 +00:00
Compare commits
62 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
01c27b56ef | ||
|
|
0d8fb8cf25 | ||
|
|
6562e3ab8c | ||
|
|
c93650ffd3 | ||
|
|
e6a2825065 | ||
|
|
0c2a0b0010 | ||
|
|
a332c51249 | ||
|
|
0b6d0bc016 | ||
|
|
e6336b1451 | ||
|
|
46290c4d37 | ||
|
|
ff2b7563c8 | ||
|
|
b9572420ed | ||
|
|
35ebb9c2aa | ||
|
|
3ebeb29dc0 | ||
|
|
8e98068538 | ||
|
|
6a72594faf | ||
|
|
728729094a | ||
|
|
93d540fbd2 | ||
|
|
eb9b6ce717 | ||
|
|
f716d42d26 | ||
|
|
1c4c364f06 | ||
|
|
162ad91547 | ||
|
|
2950e5ede4 | ||
|
|
73b041d8d2 | ||
|
|
7bf008a9cb | ||
|
|
4d9e3ccfb4 | ||
|
|
1bfe19f26c | ||
|
|
a371cedb67 | ||
|
|
4ed9c36ebd | ||
|
|
e24b23ce7e | ||
|
|
19fe6e2423 | ||
|
|
aec09f178b | ||
|
|
ffe51bae07 | ||
|
|
68231d5edb | ||
|
|
e1ea5c402c | ||
|
|
34b2c2c8b4 | ||
|
|
5d96fe6aa0 | ||
|
|
d2b5084b42 | ||
|
|
81fb0734d5 | ||
|
|
3639ce44e5 | ||
|
|
a7c00d60d5 | ||
|
|
932750b62d | ||
|
|
c90ffed67f | ||
|
|
e92c4486aa | ||
|
|
aaceea5338 | ||
|
|
4d54d180bc | ||
|
|
8fdd98e34d | ||
|
|
d53c5ee5e6 | ||
|
|
4082e4e2b8 | ||
|
|
0c689459cb | ||
|
|
40ef02f215 | ||
|
|
d369f0bb17 | ||
|
|
425d0293cc | ||
|
|
b621650975 | ||
|
|
40948160fe | ||
|
|
aa6b9dd295 | ||
|
|
05c2232b97 | ||
|
|
8f6325d529 | ||
|
|
0aa681043d | ||
|
|
40bddfdfeb | ||
|
|
d6e2f01d70 | ||
|
|
2344d3d34d |
36
.env.example
36
.env.example
@@ -8,32 +8,42 @@ MAIL_FROM_NAME=
|
|||||||
MAIL_FROM_ADDRESS=
|
MAIL_FROM_ADDRESS=
|
||||||
|
|
||||||
# Database
|
# Database
|
||||||
DB_USER=
|
DB_HOST=mysql
|
||||||
DB_HOST=
|
DB_USER=bigcapital
|
||||||
DB_PASSWORD=
|
DB_PASSWORD=bigcapital
|
||||||
DB_CHARSET=
|
DB_ROOT_PASSWORD=root
|
||||||
|
DB_CHARSET=utf8
|
||||||
|
|
||||||
# System database
|
# System database
|
||||||
SYSTEM_DB_NAME=bigcapital_system
|
SYSTEM_DB_NAME=bigcapital_system
|
||||||
|
# SYSTEM_DB_USER=
|
||||||
|
# SYSTEM_DB_PASSWORD=
|
||||||
|
# SYSTEM_DB_NAME=
|
||||||
|
# SYSTEM_DB_CHARSET=
|
||||||
|
|
||||||
# Tenants databases
|
# Tenant databases
|
||||||
TENANT_DB_NAME_PERFIX=bigcapital_tenant_
|
TENANT_DB_NAME_PERFIX=bigcapital_tenant_
|
||||||
|
# TENANT_DB_HOST=
|
||||||
# MongoDB
|
# TENANT_DB_USER=
|
||||||
MONGODB_DATABASE_URL=mongodb://localhost/bigcapital
|
# TENANT_DB_PASSWORD=
|
||||||
|
# TENANT_DB_CHARSET=
|
||||||
# Authentication
|
|
||||||
JWT_SECRET=b0JDZW56RnV6aEthb0RGPXVEcUI
|
|
||||||
|
|
||||||
# Application
|
# Application
|
||||||
BASE_URL=https://bigcapital.ly
|
BASE_URL=https://bigcapital.ly
|
||||||
CONTACT_US_MAIL=support@bigcapital.ly
|
JWT_SECRET=b0JDZW56RnV6aEthb0RGPXVEcUI
|
||||||
|
|
||||||
|
# Jobs MongoDB
|
||||||
|
MONGODB_DATABASE_URL=mongodb://localhost/bigcapital
|
||||||
|
|
||||||
|
# App proxy
|
||||||
|
PUBLIC_PROXY_PORT=80
|
||||||
|
PUBLIC_PROXY_SSL_PORT=443
|
||||||
|
|
||||||
# Agendash
|
# Agendash
|
||||||
AGENDASH_AUTH_USER=agendash
|
AGENDASH_AUTH_USER=agendash
|
||||||
AGENDASH_AUTH_PASSWORD=123123
|
AGENDASH_AUTH_PASSWORD=123123
|
||||||
|
|
||||||
# Sign-up restrictions
|
# Sign-up restrictions
|
||||||
SIGNUP_DISABLED=true
|
SIGNUP_DISABLED=false
|
||||||
SIGNUP_ALLOWED_DOMAINS=
|
SIGNUP_ALLOWED_DOMAINS=
|
||||||
SIGNUP_ALLOWED_EMAILS=
|
SIGNUP_ALLOWED_EMAILS=
|
||||||
2
.gitattributes
vendored
Normal file
2
.gitattributes
vendored
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
docker/nginx/scripts/build-nginx.sh text eol=lf
|
||||||
|
docker/mariadb/docker-entrypoint.sh text eol=lf
|
||||||
58
CHANGELOG.md
58
CHANGELOG.md
@@ -2,6 +2,64 @@
|
|||||||
|
|
||||||
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.9.6] - 12-06-2023
|
||||||
|
|
||||||
|
`@bigcapital/webapp`
|
||||||
|
|
||||||
|
* fix: remove duplicated form submitting by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/138
|
||||||
|
* feat: add monorepo version on the application sidebar by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/136
|
||||||
|
|
||||||
|
## [0.9.5] - 11-06-2023
|
||||||
|
|
||||||
|
`@bigcapital/server`
|
||||||
|
|
||||||
|
* fix: filter ledger entries that effect contact balance to AR/AP accounts only by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/132
|
||||||
|
|
||||||
|
`@bigcapital/webapp`
|
||||||
|
|
||||||
|
* fix: catch journal error when create a journal with accounts have different currency by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/135
|
||||||
|
* fix: add duplicate icon to context menu of customers and vendors table by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/133
|
||||||
|
* fix: customer/vendor opening balance with exchange rate by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/134
|
||||||
|
|
||||||
|
## [0.9.4] - 08-06-2023
|
||||||
|
|
||||||
|
`@bigcapital/monorepo`
|
||||||
|
- fixed: docker-compose line-ending issue on Windows by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/130
|
||||||
|
|
||||||
|
`@bigcapital/server`
|
||||||
|
- fixed: Disable Webpack minification for JS class name reading.
|
||||||
|
|
||||||
|
## [0.9.3] -04-06-2023
|
||||||
|
|
||||||
|
`@bigcapital/monorepo`
|
||||||
|
* Added: Add env variable to customize the proxy public ports by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/125
|
||||||
|
* Added: Migrate the server database to MariaDB by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/128
|
||||||
|
|
||||||
|
## [0.9.2] - 31-05-2023
|
||||||
|
|
||||||
|
`@bigcapital/webapp`
|
||||||
|
|
||||||
|
- fixed: move `packaeg-lock.json` inside docker container.
|
||||||
|
- fixed: remove Sentry from the web client.
|
||||||
|
|
||||||
|
## [0.9.1] - 28-05-2023
|
||||||
|
|
||||||
|
`@bigcapital/server`
|
||||||
|
- fix: deleting ledger entries of manual journal.
|
||||||
|
- fix: base currency should be enabled.
|
||||||
|
- fix: delete invoice transaction issue.
|
||||||
|
|
||||||
|
`@bigcapital/webapp`
|
||||||
|
- fix: general, accoutant and items preferences.
|
||||||
|
- fix: auto-increment sale invoices, estiamtes, credit notes, payments and manual journals.
|
||||||
|
- refactor: the setup organization form to use binded Formik components.
|
||||||
|
|
||||||
|
## [0.9.0] - 06-05-2023
|
||||||
|
|
||||||
|
`@bigcapital/server`
|
||||||
|
|
||||||
|
- [Sign-up restrictions](https://docs.bigcapital.ly/docs/deployment/signup_restriction) for self-hosting instances to disable signup or control the allowed email addresses and domains that can sign-up.
|
||||||
|
|
||||||
## [0.8.3] - 06-04-2023
|
## [0.8.3] - 06-04-2023
|
||||||
|
|
||||||
`@bigcaptial/monorepo`
|
`@bigcaptial/monorepo`
|
||||||
|
|||||||
22
README.md
22
README.md
@@ -7,6 +7,24 @@
|
|||||||
<p align="center">
|
<p align="center">
|
||||||
Simple, smart online accounting software for small and medium businesses.
|
Simple, smart online accounting software for small and medium businesses.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
|
<p align="center">
|
||||||
|
<a href="https://github.com/bigcapitalhq/bigcapital/commits/develop">
|
||||||
|
<img src="https://img.shields.io/github/commit-activity/m/bigcapitalhq/bigcapital/develop" />
|
||||||
|
</a>
|
||||||
|
<a href="https://discord.com/invite/c8nPBJafeb">
|
||||||
|
<img src="https://img.shields.io/discord/1066514716752625725?label=Discord" alt="" />
|
||||||
|
</a>
|
||||||
|
<a href="https://github.com/bigcapitalhq/bigcapital/graphs/contributors">
|
||||||
|
<img src="https://img.shields.io/github/contributors/bigcapitalhq/bigcapital" alt="" />
|
||||||
|
</a>
|
||||||
|
<a href="https://github.com/bigcapitalhq/bigcapital/blob/develop/LICENSE">
|
||||||
|
<img src="https://img.shields.io/github/license/bigcapitalhq/bigcapital" alt="" />
|
||||||
|
</a>
|
||||||
|
<a href="https://twitter.com/bigcapitalhq">
|
||||||
|
<img src="https://img.shields.io/twitter/follow/bigcapitalhq?style=social" alt="twitter" />
|
||||||
|
</a>
|
||||||
|
</p>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
# What's Bigcapital?
|
# What's Bigcapital?
|
||||||
@@ -22,10 +40,10 @@ Bigcapital is a smart and open-source accounting and inventory software, Bigcapi
|
|||||||
# Resources
|
# Resources
|
||||||
|
|
||||||
- [Documentation](https://docs.bigcapital.ly/) - Learn how to use.
|
- [Documentation](https://docs.bigcapital.ly/) - Learn how to use.
|
||||||
|
- [Contribution](https://github.com/bigcapitalhq/bigcapital/blob/develop/CONTRIBUTING.md) - Welcome to any contributions.
|
||||||
- [Discord](https://discord.com/invite/c8nPBJafeb) - Ask for help.
|
- [Discord](https://discord.com/invite/c8nPBJafeb) - Ask for help.
|
||||||
- [Bug Tracker](https://github.com/bigcapitalhq/bigcapital/issues) - Notify us new bugs.
|
- [Bug Tracker](https://github.com/bigcapitalhq/bigcapital/issues) - Notify us new bugs.
|
||||||
- [Source Code](https://github.com/bigcapitalhq/bigcapital) - Github repo.
|
|
||||||
|
|
||||||
# Changlog
|
# Changelog
|
||||||
|
|
||||||
Please see [Releases](https://github.com/bigcapitalhq/bigcapital/releases) for more information what has changed recently.
|
Please see [Releases](https://github.com/bigcapitalhq/bigcapital/releases) for more information what has changed recently.
|
||||||
|
|||||||
@@ -15,8 +15,8 @@ services:
|
|||||||
- ./data/logs/nginx/:/var/log/nginx
|
- ./data/logs/nginx/:/var/log/nginx
|
||||||
- ./docker/certbot/certs/:/var/certs
|
- ./docker/certbot/certs/:/var/certs
|
||||||
ports:
|
ports:
|
||||||
- "80:80"
|
- "${PUBLIC_PROXY_PORT:-80}:80"
|
||||||
- "443:443"
|
- "${PUBLIC_PROXY_SSL_PORT:-443}:443"
|
||||||
tty: true
|
tty: true
|
||||||
depends_on:
|
depends_on:
|
||||||
- server
|
- server
|
||||||
@@ -94,12 +94,12 @@ services:
|
|||||||
mysql:
|
mysql:
|
||||||
container_name: bigcapital-mysql
|
container_name: bigcapital-mysql
|
||||||
build:
|
build:
|
||||||
context: ./docker/mysql
|
context: ./docker/mariadb
|
||||||
environment:
|
environment:
|
||||||
- MYSQL_DATABASE=${SYSTEM_DB_NAME}
|
- MYSQL_DATABASE=${SYSTEM_DB_NAME}
|
||||||
- MYSQL_USER=${DB_USER}
|
- MYSQL_USER=${DB_USER}
|
||||||
- MYSQL_PASSWORD=${DB_PASSWORD}
|
- MYSQL_PASSWORD=${DB_PASSWORD}
|
||||||
- MYSQL_ROOT_PASSWORD=${DB_PASSWORD}
|
- MYSQL_ROOT_PASSWORD=${DB_ROOT_PASSWORD}
|
||||||
volumes:
|
volumes:
|
||||||
- mysql:/var/lib/mysql
|
- mysql:/var/lib/mysql
|
||||||
expose:
|
expose:
|
||||||
|
|||||||
@@ -6,14 +6,14 @@
|
|||||||
version: '3.3'
|
version: '3.3'
|
||||||
|
|
||||||
services:
|
services:
|
||||||
mysql:
|
mariadb:
|
||||||
build:
|
build:
|
||||||
context: ./docker/mysql
|
context: ./docker/mariadb
|
||||||
environment:
|
environment:
|
||||||
- MYSQL_DATABASE=${SYSTEM_DB_NAME}
|
- MYSQL_DATABASE=${SYSTEM_DB_NAME}
|
||||||
- MYSQL_USER=${DB_USER}
|
- MYSQL_USER=${DB_USER}
|
||||||
- MYSQL_PASSWORD=${DB_PASSWORD}
|
- MYSQL_PASSWORD=${DB_PASSWORD}
|
||||||
- MYSQL_ROOT_PASSWORD=${DB_PASSWORD}
|
- MYSQL_ROOT_PASSWORD=${DB_ROOT_PASSWORD}
|
||||||
volumes:
|
volumes:
|
||||||
- mysql:/var/lib/mysql
|
- mysql:/var/lib/mysql
|
||||||
expose:
|
expose:
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
FROM mysql:5.7
|
FROM mariadb:10.2
|
||||||
|
|
||||||
USER root
|
USER root
|
||||||
ADD my.cnf /etc/mysql/conf.d/my.cnf
|
ADD my.cnf /etc/mysql/conf.d/my.cnf
|
||||||
@@ -17,7 +17,7 @@ ENV MYSQL_ROOT_PASSWORD=$MYSQL_ROOT_PASSWORD
|
|||||||
COPY ./init.sql /scripts/init.template.sql
|
COPY ./init.sql /scripts/init.template.sql
|
||||||
COPY ./docker-entrypoint.sh /docker-entrypoint-initdb.d/docker-initialize.sh
|
COPY ./docker-entrypoint.sh /docker-entrypoint-initdb.d/docker-initialize.sh
|
||||||
|
|
||||||
# The scripts in the docker-entrypoint-initdb.d/ directory are executed as
|
# The scripts in the `docker-entrypoint-initdb.d/` directory are executed as
|
||||||
# the mysql user inside the MySQL Docker container.
|
# the mysql user inside the MySQL Docker container.
|
||||||
RUN chown -R mysql:root /docker-entrypoint-initdb.d
|
RUN chown -R mysql:root /docker-entrypoint-initdb.d
|
||||||
RUN chown -R mysql:root /scripts
|
RUN chown -R mysql:root /scripts
|
||||||
@@ -1,2 +1,3 @@
|
|||||||
GRANT ALL PRIVILEGES ON *.* TO '{MYSQL_USER}'@'%' IDENTIFIED BY '{MYSQL_PASSWORD}' WITH GRANT OPTION;
|
GRANT ALL PRIVILEGES ON *.* TO '{MYSQL_USER}'@'%' IDENTIFIED BY '{MYSQL_PASSWORD}' WITH GRANT OPTION;
|
||||||
|
|
||||||
FLUSH PRIVILEGES;
|
FLUSH PRIVILEGES;
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"$schema": "node_modules/lerna/schemas/lerna-schema.json",
|
"$schema": "node_modules/lerna/schemas/lerna-schema.json",
|
||||||
"useWorkspaces": true,
|
"useWorkspaces": true,
|
||||||
"version": "0.0.0",
|
"version": "0.9.6",
|
||||||
"npmClient": "npm"
|
"npmClient": "npm"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@bigcapital/server",
|
"name": "@bigcapital/server",
|
||||||
"version": "1.7.1",
|
"version": "0.9.5",
|
||||||
"description": "",
|
"description": "",
|
||||||
"main": "src/server.ts",
|
"main": "src/server.ts",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
|||||||
@@ -65,6 +65,9 @@ exports.getCommonWebpackOptions = ({
|
|||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
optimization: {
|
||||||
|
minimize: false,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
if (isDev) {
|
if (isDev) {
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ export default class BalanceSheetStatementController extends BaseFinancialReport
|
|||||||
get balanceSheetValidationSchema(): ValidationChain[] {
|
get balanceSheetValidationSchema(): ValidationChain[] {
|
||||||
return [
|
return [
|
||||||
...this.sheetNumberFormatValidationSchema,
|
...this.sheetNumberFormatValidationSchema,
|
||||||
query('accounting_method').optional().isIn(['cash', 'accural']),
|
query('accounting_method').optional().isIn(['cash', 'accrual']),
|
||||||
|
|
||||||
query('from_date').optional(),
|
query('from_date').optional(),
|
||||||
query('to_date').optional(),
|
query('to_date').optional(),
|
||||||
|
|||||||
@@ -58,7 +58,7 @@ export default class OrganizationController extends BaseController {
|
|||||||
private get organizationValidationSchema(): ValidationChain[] {
|
private get organizationValidationSchema(): ValidationChain[] {
|
||||||
return [
|
return [
|
||||||
check('name').exists().trim(),
|
check('name').exists().trim(),
|
||||||
check('industry').optional().isString(),
|
check('industry').optional({ nullable: true }).isString().trim().escape(),
|
||||||
check('location').exists().isString().isISO31661Alpha2(),
|
check('location').exists().isString().isISO31661Alpha2(),
|
||||||
check('base_currency').exists().isISO4217(),
|
check('base_currency').exists().isISO4217(),
|
||||||
check('timezone').exists().isIn(moment.tz.names()),
|
check('timezone').exists().isIn(moment.tz.names()),
|
||||||
|
|||||||
@@ -6,14 +6,14 @@ export default class SeedAccounts extends TenantSeeder {
|
|||||||
* Seeds initial accounts to the organization.
|
* Seeds initial accounts to the organization.
|
||||||
*/
|
*/
|
||||||
up(knex) {
|
up(knex) {
|
||||||
const data = AccountsData.map((account) => {
|
const data = AccountsData.map((account) => ({
|
||||||
return {
|
...account,
|
||||||
...account,
|
name: this.i18n.__(account.name),
|
||||||
name: this.i18n.__(account.name),
|
description: this.i18n.__(account.description),
|
||||||
description: this.i18n.__(account.description),
|
currencyCode: this.tenant.metadata.baseCurrency,
|
||||||
currencyCode: this.tenant.metadata.baseCurrency,
|
seededAt: new Date(),
|
||||||
};
|
})
|
||||||
});
|
);
|
||||||
return knex('accounts').then(async () => {
|
return knex('accounts').then(async () => {
|
||||||
// Inserts seed entries.
|
// Inserts seed entries.
|
||||||
return knex('accounts').insert(data);
|
return knex('accounts').insert(data);
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ export default class SeedSettings extends TenantSeeder {
|
|||||||
up() {
|
up() {
|
||||||
const settings = [
|
const settings = [
|
||||||
// Orgnization settings.
|
// Orgnization settings.
|
||||||
{ group: 'organization', key: 'accounting_basis', value: 'accural' },
|
{ group: 'organization', key: 'accounting_basis', value: 'accrual' },
|
||||||
|
|
||||||
// Accounts settings.
|
// Accounts settings.
|
||||||
{ group: 'accounts', key: 'account_code_unique', value: true },
|
{ group: 'accounts', key: 'account_code_unique', value: true },
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ export interface IBalanceSheetQuery extends IFinancialSheetBranchesQuery {
|
|||||||
numberFormat: INumberFormatQuery;
|
numberFormat: INumberFormatQuery;
|
||||||
noneTransactions: boolean;
|
noneTransactions: boolean;
|
||||||
noneZero: boolean;
|
noneZero: boolean;
|
||||||
basis: 'cash' | 'accural';
|
basis: 'cash' | 'accrual';
|
||||||
accountIds: number[];
|
accountIds: number[];
|
||||||
|
|
||||||
percentageOfColumn: boolean;
|
percentageOfColumn: boolean;
|
||||||
|
|||||||
@@ -4,6 +4,8 @@ export interface ILedger {
|
|||||||
|
|
||||||
getEntries(): ILedgerEntry[];
|
getEntries(): ILedgerEntry[];
|
||||||
|
|
||||||
|
filter(cb: (entry: ILedgerEntry) => boolean): ILedger;
|
||||||
|
|
||||||
whereAccountId(accountId: number): ILedger;
|
whereAccountId(accountId: number): ILedger;
|
||||||
whereContactId(contactId: number): ILedger;
|
whereContactId(contactId: number): ILedger;
|
||||||
whereFromDate(fromDate: Date | string): ILedger;
|
whereFromDate(fromDate: Date | string): ILedger;
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ export interface ITrialBalanceSheetQuery {
|
|||||||
fromDate: Date | string;
|
fromDate: Date | string;
|
||||||
toDate: Date | string;
|
toDate: Date | string;
|
||||||
numberFormat: INumberFormatQuery;
|
numberFormat: INumberFormatQuery;
|
||||||
basis: 'cash' | 'accural';
|
basis: 'cash' | 'accrual';
|
||||||
noneZero: boolean;
|
noneZero: boolean;
|
||||||
noneTransactions: boolean;
|
noneTransactions: boolean;
|
||||||
onlyActive: boolean;
|
onlyActive: boolean;
|
||||||
|
|||||||
@@ -1,9 +1,14 @@
|
|||||||
import { Service, Inject } from 'typedi';
|
import { Service, Inject } from 'typedi';
|
||||||
import async from 'async';
|
import async from 'async';
|
||||||
import { Knex } from 'knex';
|
import { Knex } from 'knex';
|
||||||
import { ILedger, ISaleContactsBalanceQueuePayload } from '@/interfaces';
|
import {
|
||||||
|
ILedger,
|
||||||
|
ILedgerEntry,
|
||||||
|
ISaleContactsBalanceQueuePayload,
|
||||||
|
} from '@/interfaces';
|
||||||
import HasTenancyService from '@/services/Tenancy/TenancyService';
|
import HasTenancyService from '@/services/Tenancy/TenancyService';
|
||||||
import { TenantMetadata } from '@/system/models';
|
import { TenantMetadata } from '@/system/models';
|
||||||
|
import { ACCOUNT_TYPE } from '@/data/AccountTypes';
|
||||||
|
|
||||||
@Service()
|
@Service()
|
||||||
export class LedgerContactsBalanceStorage {
|
export class LedgerContactsBalanceStorage {
|
||||||
@@ -49,6 +54,29 @@ export class LedgerContactsBalanceStorage {
|
|||||||
await this.saveContactBalance(tenantId, ledger, contactId, trx);
|
await this.saveContactBalance(tenantId, ledger, contactId, trx);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Filters AP/AR ledger entries.
|
||||||
|
* @param {number} tenantId
|
||||||
|
* @param {Knex.Transaction} trx
|
||||||
|
* @returns {Promise<(entry: ILedgerEntry) => boolean>}
|
||||||
|
*/
|
||||||
|
private filterARAPLedgerEntris = async (
|
||||||
|
tenantId: number,
|
||||||
|
trx?: Knex.Transaction
|
||||||
|
): Promise<(entry: ILedgerEntry) => boolean> => {
|
||||||
|
const { Account } = this.tenancy.models(tenantId);
|
||||||
|
|
||||||
|
const ARAPAcounts = await Account.query(trx).whereIn('accountType', [
|
||||||
|
ACCOUNT_TYPE.ACCOUNTS_RECEIVABLE,
|
||||||
|
ACCOUNT_TYPE.ACCOUNTS_PAYABLE,
|
||||||
|
]);
|
||||||
|
const ARAPAcountsIds = ARAPAcounts.map((a) => a.id);
|
||||||
|
|
||||||
|
return (entry: ILedgerEntry) => {
|
||||||
|
return ARAPAcountsIds.indexOf(entry.accountId) !== -1;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @param {number} tenantId
|
* @param {number} tenantId
|
||||||
@@ -63,7 +91,7 @@ export class LedgerContactsBalanceStorage {
|
|||||||
trx?: Knex.Transaction
|
trx?: Knex.Transaction
|
||||||
): Promise<void> => {
|
): Promise<void> => {
|
||||||
const { Contact } = this.tenancy.models(tenantId);
|
const { Contact } = this.tenancy.models(tenantId);
|
||||||
const contact = await Contact.query().findById(contactId);
|
const contact = await Contact.query(trx).findById(contactId);
|
||||||
|
|
||||||
// Retrieves the given tenant metadata.
|
// Retrieves the given tenant metadata.
|
||||||
const tenantMeta = await TenantMetadata.query().findOne({ tenantId });
|
const tenantMeta = await TenantMetadata.query().findOne({ tenantId });
|
||||||
@@ -72,7 +100,15 @@ export class LedgerContactsBalanceStorage {
|
|||||||
const isForeignContact = contact.currencyCode !== tenantMeta.baseCurrency;
|
const isForeignContact = contact.currencyCode !== tenantMeta.baseCurrency;
|
||||||
|
|
||||||
// Filters the ledger base on the given contact id.
|
// Filters the ledger base on the given contact id.
|
||||||
const contactLedger = ledger.whereContactId(contactId);
|
const filterARAPLedgerEntris = await this.filterARAPLedgerEntris(
|
||||||
|
tenantId,
|
||||||
|
trx
|
||||||
|
);
|
||||||
|
const contactLedger = ledger
|
||||||
|
// Filter entries only that have contact id.
|
||||||
|
.whereContactId(contactId)
|
||||||
|
// Filter entries on AR/AP accounts.
|
||||||
|
.filter(filterARAPLedgerEntris);
|
||||||
|
|
||||||
const closingBalance = isForeignContact
|
const closingBalance = isForeignContact
|
||||||
? contactLedger
|
? contactLedger
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ export class LedgerRevert {
|
|||||||
private tenancy: HasTenancyService;
|
private tenancy: HasTenancyService;
|
||||||
|
|
||||||
@Inject()
|
@Inject()
|
||||||
ledgerStorage: LedgerStorageService;
|
private ledgerStorage: LedgerStorageService;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reverts the jouranl entries.
|
* Reverts the jouranl entries.
|
||||||
|
|||||||
@@ -55,7 +55,7 @@ export class CreateCustomer {
|
|||||||
} as ICustomerEventCreatingPayload);
|
} as ICustomerEventCreatingPayload);
|
||||||
|
|
||||||
// Creates a new contact as customer.
|
// Creates a new contact as customer.
|
||||||
const customer = await Contact.query().insertAndFetch({
|
const customer = await Contact.query(trx).insertAndFetch({
|
||||||
...customerObj,
|
...customerObj,
|
||||||
});
|
});
|
||||||
// Triggers `onCustomerCreated` event.
|
// Triggers `onCustomerCreated` event.
|
||||||
|
|||||||
@@ -5,18 +5,13 @@ import {
|
|||||||
ICreditNoteDeletedPayload,
|
ICreditNoteDeletedPayload,
|
||||||
ICreditNoteEditedPayload,
|
ICreditNoteEditedPayload,
|
||||||
ICreditNoteOpenedPayload,
|
ICreditNoteOpenedPayload,
|
||||||
IRefundCreditNoteOpenedPayload,
|
|
||||||
} from '@/interfaces';
|
} from '@/interfaces';
|
||||||
import CreditNoteGLEntries from './CreditNoteGLEntries';
|
import CreditNoteGLEntries from './CreditNoteGLEntries';
|
||||||
import HasTenancyService from '@/services/Tenancy/TenancyService';
|
|
||||||
|
|
||||||
@Service()
|
@Service()
|
||||||
export default class CreditNoteGLEntriesSubscriber {
|
export default class CreditNoteGLEntriesSubscriber {
|
||||||
@Inject()
|
@Inject()
|
||||||
creditNoteGLEntries: CreditNoteGLEntries;
|
private creditNoteGLEntries: CreditNoteGLEntries;
|
||||||
|
|
||||||
@Inject()
|
|
||||||
tenancy: HasTenancyService;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Attaches events with handlers.
|
* Attaches events with handlers.
|
||||||
|
|||||||
@@ -9,7 +9,6 @@ import events from '@/subscribers/events';
|
|||||||
import UnitOfWork from '@/services/UnitOfWork';
|
import UnitOfWork from '@/services/UnitOfWork';
|
||||||
import { EventPublisher } from '@/lib/EventPublisher/EventPublisher';
|
import { EventPublisher } from '@/lib/EventPublisher/EventPublisher';
|
||||||
import { CommandExpenseValidator } from './CommandExpenseValidator';
|
import { CommandExpenseValidator } from './CommandExpenseValidator';
|
||||||
import { ExpenseCategory } from 'models';
|
|
||||||
import HasTenancyService from '@/services/Tenancy/TenancyService';
|
import HasTenancyService from '@/services/Tenancy/TenancyService';
|
||||||
|
|
||||||
@Service()
|
@Service()
|
||||||
@@ -37,7 +36,7 @@ export class DeleteExpense {
|
|||||||
expenseId: number,
|
expenseId: number,
|
||||||
authorizedUser: ISystemUser
|
authorizedUser: ISystemUser
|
||||||
): Promise<void> => {
|
): Promise<void> => {
|
||||||
const { Expense } = this.tenancy.models(tenantId);
|
const { Expense, ExpenseCategory } = this.tenancy.models(tenantId);
|
||||||
|
|
||||||
// Retrieves the expense transaction with associated entries or
|
// Retrieves the expense transaction with associated entries or
|
||||||
// throw not found error.
|
// throw not found error.
|
||||||
@@ -60,7 +59,7 @@ export class DeleteExpense {
|
|||||||
} as IExpenseDeletingPayload);
|
} as IExpenseDeletingPayload);
|
||||||
|
|
||||||
// Deletes expense associated entries.
|
// Deletes expense associated entries.
|
||||||
await ExpenseCategory.query(trx).findById(expenseId).delete();
|
await ExpenseCategory.query(trx).where('expenseId', expenseId).delete();
|
||||||
|
|
||||||
// Deletes expense transactions.
|
// Deletes expense transactions.
|
||||||
await Expense.query(trx).findById(expenseId).delete();
|
await Expense.query(trx).findById(expenseId).delete();
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ export class ExpenseGLEntries {
|
|||||||
...commonEntry,
|
...commonEntry,
|
||||||
credit: expense.localAmount,
|
credit: expense.localAmount,
|
||||||
accountId: expense.paymentAccountId,
|
accountId: expense.paymentAccountId,
|
||||||
accountNormal: AccountNormal.CREDIT,
|
accountNormal: AccountNormal.DEBIT,
|
||||||
index: 1,
|
index: 1,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ export const getDefaultPLQuery = (): IProfitLossSheetQuery => ({
|
|||||||
formatMoney: 'total',
|
formatMoney: 'total',
|
||||||
precision: 2,
|
precision: 2,
|
||||||
},
|
},
|
||||||
basis: 'accural',
|
basis: 'accrual',
|
||||||
|
|
||||||
noneZero: false,
|
noneZero: false,
|
||||||
noneTransactions: false,
|
noneTransactions: false,
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ export default class TrialBalanceSheetService extends FinancialSheet {
|
|||||||
formatMoney: 'total',
|
formatMoney: 'total',
|
||||||
precision: 2,
|
precision: 2,
|
||||||
},
|
},
|
||||||
basis: 'accural',
|
basis: 'accrual',
|
||||||
noneZero: false,
|
noneZero: false,
|
||||||
noneTransactions: true,
|
noneTransactions: true,
|
||||||
onlyActive: false,
|
onlyActive: false,
|
||||||
|
|||||||
@@ -1,11 +1,10 @@
|
|||||||
import { difference, sumBy, omit, map } from 'lodash';
|
import { difference } from 'lodash';
|
||||||
import { Service, Inject } from 'typedi';
|
import { Service, Inject } from 'typedi';
|
||||||
import { ServiceError } from '@/exceptions';
|
import { ServiceError } from '@/exceptions';
|
||||||
import {
|
import {
|
||||||
IManualJournalDTO,
|
IManualJournalDTO,
|
||||||
IManualJournalEntry,
|
IManualJournalEntry,
|
||||||
IManualJournal,
|
IManualJournal,
|
||||||
IManualJournalEntryDTO,
|
|
||||||
} from '@/interfaces';
|
} from '@/interfaces';
|
||||||
import TenancyService from '@/services/Tenancy/TenancyService';
|
import TenancyService from '@/services/Tenancy/TenancyService';
|
||||||
import { ERRORS } from './constants';
|
import { ERRORS } from './constants';
|
||||||
@@ -286,7 +285,7 @@ export class CommandManualJournalValidators {
|
|||||||
public validateJournalCurrencyWithAccountsCurrency = async (
|
public validateJournalCurrencyWithAccountsCurrency = async (
|
||||||
tenantId: number,
|
tenantId: number,
|
||||||
manualJournalDTO: IManualJournalDTO,
|
manualJournalDTO: IManualJournalDTO,
|
||||||
baseCurrency: string,
|
baseCurrency: string
|
||||||
) => {
|
) => {
|
||||||
const { Account } = this.tenancy.models(tenantId);
|
const { Account } = this.tenancy.models(tenantId);
|
||||||
|
|
||||||
|
|||||||
@@ -3,25 +3,20 @@ import * as R from 'ramda';
|
|||||||
import {
|
import {
|
||||||
IManualJournal,
|
IManualJournal,
|
||||||
IManualJournalEntry,
|
IManualJournalEntry,
|
||||||
IAccount,
|
|
||||||
ILedgerEntry,
|
ILedgerEntry,
|
||||||
} from '@/interfaces';
|
} from '@/interfaces';
|
||||||
import { Knex } from 'knex';
|
import { Knex } from 'knex';
|
||||||
import Ledger from '@/services/Accounting/Ledger';
|
import Ledger from '@/services/Accounting/Ledger';
|
||||||
import LedgerStorageService from '@/services/Accounting/LedgerStorageService';
|
import LedgerStorageService from '@/services/Accounting/LedgerStorageService';
|
||||||
import HasTenancyService from '@/services/Tenancy/TenancyService';
|
import HasTenancyService from '@/services/Tenancy/TenancyService';
|
||||||
import { LedgerRevert } from '@/services/Accounting/LedgerStorageRevert';
|
|
||||||
|
|
||||||
@Service()
|
@Service()
|
||||||
export class ManualJournalGLEntries {
|
export class ManualJournalGLEntries {
|
||||||
@Inject()
|
@Inject()
|
||||||
ledgerStorage: LedgerStorageService;
|
private ledgerStorage: LedgerStorageService;
|
||||||
|
|
||||||
@Inject()
|
@Inject()
|
||||||
ledgerRevert: LedgerRevert;
|
private tenancy: HasTenancyService;
|
||||||
|
|
||||||
@Inject()
|
|
||||||
tenancy: HasTenancyService;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create manual journal GL entries.
|
* Create manual journal GL entries.
|
||||||
@@ -77,7 +72,7 @@ export class ManualJournalGLEntries {
|
|||||||
manualJournalId: number,
|
manualJournalId: number,
|
||||||
trx?: Knex.Transaction
|
trx?: Knex.Transaction
|
||||||
): Promise<void> => {
|
): Promise<void> => {
|
||||||
return this.ledgerRevert.revertGLEntries(
|
return this.ledgerStorage.deleteByReference(
|
||||||
tenantId,
|
tenantId,
|
||||||
manualJournalId,
|
manualJournalId,
|
||||||
'Journal',
|
'Journal',
|
||||||
@@ -86,7 +81,7 @@ export class ManualJournalGLEntries {
|
|||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
* Retrieves the ledger of the given manual journal.
|
||||||
* @param {IManualJournal} manualJournal
|
* @param {IManualJournal} manualJournal
|
||||||
* @returns {Ledger}
|
* @returns {Ledger}
|
||||||
*/
|
*/
|
||||||
@@ -97,11 +92,13 @@ export class ManualJournalGLEntries {
|
|||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
* Retrieves the common entry details of the manual journal
|
||||||
* @param {IManualJournal} manualJournal
|
* @param {IManualJournal} manualJournal
|
||||||
* @returns {}
|
* @returns {Partial<ILedgerEntry>}
|
||||||
*/
|
*/
|
||||||
private getManualJournalCommonEntry = (manualJournal: IManualJournal) => {
|
private getManualJournalCommonEntry = (
|
||||||
|
manualJournal: IManualJournal
|
||||||
|
): Partial<ILedgerEntry> => {
|
||||||
return {
|
return {
|
||||||
transactionNumber: manualJournal.journalNumber,
|
transactionNumber: manualJournal.journalNumber,
|
||||||
referenceNumber: manualJournal.reference,
|
referenceNumber: manualJournal.reference,
|
||||||
@@ -118,7 +115,8 @@ export class ManualJournalGLEntries {
|
|||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
* Retrieves the ledger entry of the given manual journal and
|
||||||
|
* its associated entry.
|
||||||
* @param {IManualJournal} manualJournal -
|
* @param {IManualJournal} manualJournal -
|
||||||
* @param {IManualJournalEntry} entry -
|
* @param {IManualJournalEntry} entry -
|
||||||
* @returns {ILedgerEntry}
|
* @returns {ILedgerEntry}
|
||||||
@@ -149,7 +147,7 @@ export class ManualJournalGLEntries {
|
|||||||
);
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
* Retrieves the ledger of the given manual journal.
|
||||||
* @param {IManualJournal} manualJournal
|
* @param {IManualJournal} manualJournal
|
||||||
* @returns {ILedgerEntry[]}
|
* @returns {ILedgerEntry[]}
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -23,8 +23,11 @@ export class ProjectBillableBillSubscriber {
|
|||||||
events.saleInvoice.onCreated,
|
events.saleInvoice.onCreated,
|
||||||
this.handleIncreaseBillableBill
|
this.handleIncreaseBillableBill
|
||||||
);
|
);
|
||||||
bus.subscribe(events.saleInvoice.onEdited, this.handleDecreaseBillableBill);
|
bus.subscribe(events.saleInvoice.onEdited, this.handleEditBillableBill);
|
||||||
bus.subscribe(events.saleInvoice.onDeleted, this.handleEditBillableBill);
|
bus.subscribe(
|
||||||
|
events.saleInvoice.onDeleted,
|
||||||
|
this.handleDecreaseBillableBill
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -1,7 +1,11 @@
|
|||||||
import { Knex } from 'knex';
|
import { Knex } from 'knex';
|
||||||
import { Inject, Service } from 'typedi';
|
import { Inject, Service } from 'typedi';
|
||||||
import async from 'async';
|
import async from 'async';
|
||||||
import { ISaleInvoice, ISaleInvoiceDTO, ProjectLinkRefType } from '@/interfaces';
|
import {
|
||||||
|
ISaleInvoice,
|
||||||
|
ISaleInvoiceDTO,
|
||||||
|
ProjectLinkRefType,
|
||||||
|
} from '@/interfaces';
|
||||||
import { ProjectBillableExpense } from './ProjectBillableExpense';
|
import { ProjectBillableExpense } from './ProjectBillableExpense';
|
||||||
import { filterEntriesByRefType } from './_utils';
|
import { filterEntriesByRefType } from './_utils';
|
||||||
|
|
||||||
|
|||||||
@@ -21,13 +21,10 @@ export class ProjectBillableExpensesSubscriber {
|
|||||||
events.saleInvoice.onCreated,
|
events.saleInvoice.onCreated,
|
||||||
this.handleIncreaseBillableExpenses
|
this.handleIncreaseBillableExpenses
|
||||||
);
|
);
|
||||||
bus.subscribe(
|
bus.subscribe(events.saleInvoice.onEdited, this.handleEditBillableExpenses);
|
||||||
events.saleInvoice.onEdited,
|
|
||||||
this.handleDecreaseBillableExpenses
|
|
||||||
);
|
|
||||||
bus.subscribe(
|
bus.subscribe(
|
||||||
events.saleInvoice.onDeleted,
|
events.saleInvoice.onDeleted,
|
||||||
this.handleEditBillableExpenses
|
this.handleDecreaseBillableExpenses
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -5,10 +5,10 @@ USER root
|
|||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
|
|
||||||
# Install dependencies
|
# Install dependencies
|
||||||
COPY package.json ./
|
COPY package*.json ./
|
||||||
COPY lerna.json ./
|
COPY lerna.json ./
|
||||||
|
|
||||||
COPY ./packages/webapp/package.json /app/packages/webapp/package.json
|
COPY ./packages/webapp/package*.json /app/packages/webapp/
|
||||||
|
|
||||||
RUN npm install
|
RUN npm install
|
||||||
RUN npm run bootstrap
|
RUN npm run bootstrap
|
||||||
|
|||||||
@@ -1,7 +1,18 @@
|
|||||||
const path = require('path');
|
const path = require('path');
|
||||||
|
const webpack = require('webpack');
|
||||||
|
const dotenv = require('dotenv-webpack');
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
webpack: {
|
webpack: {
|
||||||
|
plugins: [
|
||||||
|
new dotenv(),
|
||||||
|
new webpack.DefinePlugin({
|
||||||
|
'process.env': {
|
||||||
|
MONOREPO_VERSION: JSON.stringify(require('../../lerna.json').version),
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
|
||||||
alias: {
|
alias: {
|
||||||
'@': path.resolve(__dirname, 'src'),
|
'@': path.resolve(__dirname, 'src'),
|
||||||
},
|
},
|
||||||
|
|||||||
158
packages/webapp/package-lock.json
generated
158
packages/webapp/package-lock.json
generated
@@ -1205,9 +1205,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@blueprintjs-formik/core": {
|
"@blueprintjs-formik/core": {
|
||||||
"version": "0.2.1",
|
"version": "0.3.3",
|
||||||
"resolved": "https://registry.npmjs.org/@blueprintjs-formik/core/-/core-0.2.1.tgz",
|
"resolved": "https://registry.npmjs.org/@blueprintjs-formik/core/-/core-0.3.3.tgz",
|
||||||
"integrity": "sha512-YGJe+QorDGbkWDSUg6x69LYGN62Kgvb92Iz/voqmszVRKj4KcoPvd/7coF8Jmu+ZQE6LcwM/9ccB2i63L99ITA==",
|
"integrity": "sha512-ko7g54YSEcSq2K/GEpmiTG0foGLqe7DwgXGhkGxYEiHhLAUv8WvQmrFsm8e/KOW7n8mLGq0uaZVe2l8m3JTGGQ==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"lodash.get": "^4.4.2",
|
"lodash.get": "^4.4.2",
|
||||||
"lodash.keyby": "^4.6.0",
|
"lodash.keyby": "^4.6.0",
|
||||||
@@ -1929,137 +1929,6 @@
|
|||||||
"reselect": "^4.1.7"
|
"reselect": "^4.1.7"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@sentry/browser": {
|
|
||||||
"version": "6.19.7",
|
|
||||||
"resolved": "https://registry.npmjs.org/@sentry/browser/-/browser-6.19.7.tgz",
|
|
||||||
"integrity": "sha512-oDbklp4O3MtAM4mtuwyZLrgO1qDVYIujzNJQzXmi9YzymJCuzMLSRDvhY83NNDCRxf0pds4DShgYeZdbSyKraA==",
|
|
||||||
"requires": {
|
|
||||||
"@sentry/core": "6.19.7",
|
|
||||||
"@sentry/types": "6.19.7",
|
|
||||||
"@sentry/utils": "6.19.7",
|
|
||||||
"tslib": "^1.9.3"
|
|
||||||
},
|
|
||||||
"dependencies": {
|
|
||||||
"tslib": {
|
|
||||||
"version": "1.14.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz",
|
|
||||||
"integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg=="
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"@sentry/core": {
|
|
||||||
"version": "6.19.7",
|
|
||||||
"resolved": "https://registry.npmjs.org/@sentry/core/-/core-6.19.7.tgz",
|
|
||||||
"integrity": "sha512-tOfZ/umqB2AcHPGbIrsFLcvApdTm9ggpi/kQZFkej7kMphjT+SGBiQfYtjyg9jcRW+ilAR4JXC9BGKsdEQ+8Vw==",
|
|
||||||
"requires": {
|
|
||||||
"@sentry/hub": "6.19.7",
|
|
||||||
"@sentry/minimal": "6.19.7",
|
|
||||||
"@sentry/types": "6.19.7",
|
|
||||||
"@sentry/utils": "6.19.7",
|
|
||||||
"tslib": "^1.9.3"
|
|
||||||
},
|
|
||||||
"dependencies": {
|
|
||||||
"tslib": {
|
|
||||||
"version": "1.14.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz",
|
|
||||||
"integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg=="
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"@sentry/hub": {
|
|
||||||
"version": "6.19.7",
|
|
||||||
"resolved": "https://registry.npmjs.org/@sentry/hub/-/hub-6.19.7.tgz",
|
|
||||||
"integrity": "sha512-y3OtbYFAqKHCWezF0EGGr5lcyI2KbaXW2Ik7Xp8Mu9TxbSTuwTe4rTntwg8ngPjUQU3SUHzgjqVB8qjiGqFXCA==",
|
|
||||||
"requires": {
|
|
||||||
"@sentry/types": "6.19.7",
|
|
||||||
"@sentry/utils": "6.19.7",
|
|
||||||
"tslib": "^1.9.3"
|
|
||||||
},
|
|
||||||
"dependencies": {
|
|
||||||
"tslib": {
|
|
||||||
"version": "1.14.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz",
|
|
||||||
"integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg=="
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"@sentry/minimal": {
|
|
||||||
"version": "6.19.7",
|
|
||||||
"resolved": "https://registry.npmjs.org/@sentry/minimal/-/minimal-6.19.7.tgz",
|
|
||||||
"integrity": "sha512-wcYmSJOdvk6VAPx8IcmZgN08XTXRwRtB1aOLZm+MVHjIZIhHoBGZJYTVQS/BWjldsamj2cX3YGbGXNunaCfYJQ==",
|
|
||||||
"requires": {
|
|
||||||
"@sentry/hub": "6.19.7",
|
|
||||||
"@sentry/types": "6.19.7",
|
|
||||||
"tslib": "^1.9.3"
|
|
||||||
},
|
|
||||||
"dependencies": {
|
|
||||||
"tslib": {
|
|
||||||
"version": "1.14.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz",
|
|
||||||
"integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg=="
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"@sentry/react": {
|
|
||||||
"version": "6.19.7",
|
|
||||||
"resolved": "https://registry.npmjs.org/@sentry/react/-/react-6.19.7.tgz",
|
|
||||||
"integrity": "sha512-VzJeBg/v41jfxUYPkH2WYrKjWc4YiMLzDX0f4Zf6WkJ4v3IlDDSkX6DfmWekjTKBho6wiMkSNy2hJ1dHfGZ9jA==",
|
|
||||||
"requires": {
|
|
||||||
"@sentry/browser": "6.19.7",
|
|
||||||
"@sentry/minimal": "6.19.7",
|
|
||||||
"@sentry/types": "6.19.7",
|
|
||||||
"@sentry/utils": "6.19.7",
|
|
||||||
"hoist-non-react-statics": "^3.3.2",
|
|
||||||
"tslib": "^1.9.3"
|
|
||||||
},
|
|
||||||
"dependencies": {
|
|
||||||
"tslib": {
|
|
||||||
"version": "1.14.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz",
|
|
||||||
"integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg=="
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"@sentry/tracing": {
|
|
||||||
"version": "6.19.7",
|
|
||||||
"resolved": "https://registry.npmjs.org/@sentry/tracing/-/tracing-6.19.7.tgz",
|
|
||||||
"integrity": "sha512-ol4TupNnv9Zd+bZei7B6Ygnr9N3Gp1PUrNI761QSlHtPC25xXC5ssSD3GMhBgyQrcvpuRcCFHVNNM97tN5cZiA==",
|
|
||||||
"requires": {
|
|
||||||
"@sentry/hub": "6.19.7",
|
|
||||||
"@sentry/minimal": "6.19.7",
|
|
||||||
"@sentry/types": "6.19.7",
|
|
||||||
"@sentry/utils": "6.19.7",
|
|
||||||
"tslib": "^1.9.3"
|
|
||||||
},
|
|
||||||
"dependencies": {
|
|
||||||
"tslib": {
|
|
||||||
"version": "1.14.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz",
|
|
||||||
"integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg=="
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"@sentry/types": {
|
|
||||||
"version": "6.19.7",
|
|
||||||
"resolved": "https://registry.npmjs.org/@sentry/types/-/types-6.19.7.tgz",
|
|
||||||
"integrity": "sha512-jH84pDYE+hHIbVnab3Hr+ZXr1v8QABfhx39KknxqKWr2l0oEItzepV0URvbEhB446lk/S/59230dlUUIBGsXbg=="
|
|
||||||
},
|
|
||||||
"@sentry/utils": {
|
|
||||||
"version": "6.19.7",
|
|
||||||
"resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-6.19.7.tgz",
|
|
||||||
"integrity": "sha512-z95ECmE3i9pbWoXQrD/7PgkBAzJYR+iXtPuTkpBjDKs86O3mT+PXOT3BAn79w2wkn7/i3vOGD2xVr1uiMl26dA==",
|
|
||||||
"requires": {
|
|
||||||
"@sentry/types": "6.19.7",
|
|
||||||
"tslib": "^1.9.3"
|
|
||||||
},
|
|
||||||
"dependencies": {
|
|
||||||
"tslib": {
|
|
||||||
"version": "1.14.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz",
|
|
||||||
"integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg=="
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"@sheerun/mutationobserver-shim": {
|
"@sheerun/mutationobserver-shim": {
|
||||||
"version": "0.3.3",
|
"version": "0.3.3",
|
||||||
"resolved": "https://registry.npmjs.org/@sheerun/mutationobserver-shim/-/mutationobserver-shim-0.3.3.tgz",
|
"resolved": "https://registry.npmjs.org/@sheerun/mutationobserver-shim/-/mutationobserver-shim-0.3.3.tgz",
|
||||||
@@ -5985,11 +5854,27 @@
|
|||||||
"resolved": "https://registry.npmjs.org/dotenv/-/dotenv-8.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/dotenv/-/dotenv-8.2.0.tgz",
|
||||||
"integrity": "sha512-8sJ78ElpbDJBHNeBzUbUVLsqKdccaa/BXF1uPTw3GrvQTBgrQrtObr2mUrE38vzYd8cEv+m/JBfDLioYcfXoaw=="
|
"integrity": "sha512-8sJ78ElpbDJBHNeBzUbUVLsqKdccaa/BXF1uPTw3GrvQTBgrQrtObr2mUrE38vzYd8cEv+m/JBfDLioYcfXoaw=="
|
||||||
},
|
},
|
||||||
|
"dotenv-defaults": {
|
||||||
|
"version": "2.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/dotenv-defaults/-/dotenv-defaults-2.0.2.tgz",
|
||||||
|
"integrity": "sha512-iOIzovWfsUHU91L5i8bJce3NYK5JXeAwH50Jh6+ARUdLiiGlYWfGw6UkzsYqaXZH/hjE/eCd/PlfM/qqyK0AMg==",
|
||||||
|
"requires": {
|
||||||
|
"dotenv": "^8.2.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"dotenv-expand": {
|
"dotenv-expand": {
|
||||||
"version": "5.1.0",
|
"version": "5.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/dotenv-expand/-/dotenv-expand-5.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/dotenv-expand/-/dotenv-expand-5.1.0.tgz",
|
||||||
"integrity": "sha512-YXQl1DSa4/PQyRfgrv6aoNjhasp/p4qs9FjJ4q4cQk+8m4r6k4ZSiEyytKG8f8W9gi8WsQtIObNmKd+tMzNTmA=="
|
"integrity": "sha512-YXQl1DSa4/PQyRfgrv6aoNjhasp/p4qs9FjJ4q4cQk+8m4r6k4ZSiEyytKG8f8W9gi8WsQtIObNmKd+tMzNTmA=="
|
||||||
},
|
},
|
||||||
|
"dotenv-webpack": {
|
||||||
|
"version": "8.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/dotenv-webpack/-/dotenv-webpack-8.0.1.tgz",
|
||||||
|
"integrity": "sha512-CdrgfhZOnx4uB18SgaoP9XHRN2v48BbjuXQsZY5ixs5A8579NxQkmMxRtI7aTwSiSQcM2ao12Fdu+L3ZS3bG4w==",
|
||||||
|
"requires": {
|
||||||
|
"dotenv-defaults": "^2.0.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
"duplexer": {
|
"duplexer": {
|
||||||
"version": "0.1.2",
|
"version": "0.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.2.tgz",
|
||||||
@@ -7298,6 +7183,11 @@
|
|||||||
"locate-path": "^3.0.0"
|
"locate-path": "^3.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"flat": {
|
||||||
|
"version": "5.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz",
|
||||||
|
"integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ=="
|
||||||
|
},
|
||||||
"flat-cache": {
|
"flat-cache": {
|
||||||
"version": "2.0.1",
|
"version": "2.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-2.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-2.0.1.tgz",
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
{
|
{
|
||||||
"name": "@bigcapital/webapp",
|
"name": "@bigcapital/webapp",
|
||||||
"version": "1.7.1",
|
"version": "0.9.6",
|
||||||
"private": true,
|
"private": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@blueprintjs-formik/core": "^0.2.1",
|
"@blueprintjs-formik/core": "^0.3.3",
|
||||||
"@blueprintjs-formik/datetime": "^0.3.4",
|
"@blueprintjs-formik/datetime": "^0.3.4",
|
||||||
"@blueprintjs-formik/select": "^0.2.3",
|
"@blueprintjs-formik/select": "^0.2.3",
|
||||||
"@blueprintjs/core": "^3.50.2",
|
"@blueprintjs/core": "^3.50.2",
|
||||||
@@ -16,8 +16,6 @@
|
|||||||
"@casl/react": "^2.3.0",
|
"@casl/react": "^2.3.0",
|
||||||
"@craco/craco": "^5.9.0",
|
"@craco/craco": "^5.9.0",
|
||||||
"@reduxjs/toolkit": "^1.2.5",
|
"@reduxjs/toolkit": "^1.2.5",
|
||||||
"@sentry/react": "^6.13.2",
|
|
||||||
"@sentry/tracing": "^6.13.2",
|
|
||||||
"@testing-library/jest-dom": "^4.2.4",
|
"@testing-library/jest-dom": "^4.2.4",
|
||||||
"@testing-library/react": "^9.4.0",
|
"@testing-library/react": "^9.4.0",
|
||||||
"@testing-library/user-event": "^7.2.1",
|
"@testing-library/user-event": "^7.2.1",
|
||||||
@@ -44,7 +42,9 @@
|
|||||||
"deep-map-keys": "^2.0.1",
|
"deep-map-keys": "^2.0.1",
|
||||||
"deepdash": "^5.3.9",
|
"deepdash": "^5.3.9",
|
||||||
"dependency-graph": "^0.11.0",
|
"dependency-graph": "^0.11.0",
|
||||||
|
"dotenv-webpack": "^8.0.1",
|
||||||
"fast-deep-equal": "^3.1.3",
|
"fast-deep-equal": "^3.1.3",
|
||||||
|
"flat": "^5.0.2",
|
||||||
"formik": "^2.2.5",
|
"formik": "^2.2.5",
|
||||||
"http-proxy-middleware": "^1.0.0",
|
"http-proxy-middleware": "^1.0.0",
|
||||||
"jest": "24.9.0",
|
"jest": "24.9.0",
|
||||||
|
|||||||
@@ -20,24 +20,6 @@
|
|||||||
-->
|
-->
|
||||||
<link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
|
<link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
|
||||||
|
|
||||||
<% if (process.env.NODE_ENV === 'production') { %>
|
|
||||||
<!-- Hotjar Tracking Code for https://app.bigcapital.ly/ -->
|
|
||||||
<script>
|
|
||||||
(function (h, o, t, j, a, r) {
|
|
||||||
h.hj =
|
|
||||||
h.hj ||
|
|
||||||
function () {
|
|
||||||
(h.hj.q = h.hj.q || []).push(arguments);
|
|
||||||
};
|
|
||||||
h._hjSettings = { hjid: 2774528, hjsv: 6 };
|
|
||||||
a = o.getElementsByTagName('head')[0];
|
|
||||||
r = o.createElement('script');
|
|
||||||
r.async = 1;
|
|
||||||
r.src = t + h._hjSettings.hjid + j + h._hjSettings.hjsv;
|
|
||||||
a.appendChild(r);
|
|
||||||
})(window, document, 'https://static.hotjar.com/c/hotjar-', '.js?sv=');
|
|
||||||
</script>
|
|
||||||
<% } %>
|
|
||||||
<!--
|
<!--
|
||||||
Notice the use of %PUBLIC_URL% in the tags above.
|
Notice the use of %PUBLIC_URL% in the tags above.
|
||||||
It will be replaced with the URL of the `public` folder during the build.
|
It will be replaced with the URL of the `public` folder during the build.
|
||||||
@@ -69,7 +51,5 @@
|
|||||||
href="https://cdnjs.cloudflare.com/ajax/libs/flexboxgrid/6.3.1/flexboxgrid.min.css"
|
href="https://cdnjs.cloudflare.com/ajax/libs/flexboxgrid/6.3.1/flexboxgrid.min.css"
|
||||||
type="text/css"
|
type="text/css"
|
||||||
/>
|
/>
|
||||||
<!-- <link href="https://cdn.syncfusion.com/ej2/material.css" rel="stylesheet"> -->
|
|
||||||
<!-- <link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet" /> -->
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
@@ -17,8 +17,8 @@ import AllocateLandedCostDialog from '@/containers/Dialogs/AllocateLandedCostDia
|
|||||||
import InvoicePdfPreviewDialog from '@/containers/Dialogs/InvoicePdfPreviewDialog';
|
import InvoicePdfPreviewDialog from '@/containers/Dialogs/InvoicePdfPreviewDialog';
|
||||||
import EstimatePdfPreviewDialog from '@/containers/Dialogs/EstimatePdfPreviewDialog';
|
import EstimatePdfPreviewDialog from '@/containers/Dialogs/EstimatePdfPreviewDialog';
|
||||||
import ReceiptPdfPreviewDialog from '@/containers/Dialogs/ReceiptPdfPreviewDialog';
|
import ReceiptPdfPreviewDialog from '@/containers/Dialogs/ReceiptPdfPreviewDialog';
|
||||||
import MoneyInDialog from '@/containers/Dialogs/MoneyInDialog';
|
import MoneyInDialog from '@/containers/CashFlow/MoneyInDialog';
|
||||||
import MoneyOutDialog from '@/containers/Dialogs/MoneyOutDialog';
|
import MoneyOutDialog from '@/containers/CashFlow/MoneyOutDialog';
|
||||||
import BadDebtDialog from '@/containers/Dialogs/BadDebtDialog';
|
import BadDebtDialog from '@/containers/Dialogs/BadDebtDialog';
|
||||||
import NotifyInvoiceViaSMSDialog from '@/containers/Dialogs/NotifyInvoiceViaSMSDialog';
|
import NotifyInvoiceViaSMSDialog from '@/containers/Dialogs/NotifyInvoiceViaSMSDialog';
|
||||||
import NotifyReceiptViaSMSDialog from '@/containers/Dialogs/NotifyReceiptViaSMSDialog';
|
import NotifyReceiptViaSMSDialog from '@/containers/Dialogs/NotifyReceiptViaSMSDialog';
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ const SelectButton = styled(Button)`
|
|||||||
margin-right: 12px;
|
margin-right: 12px;
|
||||||
border-radius: 1px;
|
border-radius: 1px;
|
||||||
}
|
}
|
||||||
&:not([class*='bp3-intent-']) {
|
&:not([class*='bp3-intent-']):not(.bp3-disabled) {
|
||||||
&,
|
&,
|
||||||
&:hover {
|
&:hover {
|
||||||
background: #fff;
|
background: #fff;
|
||||||
|
|||||||
@@ -46,4 +46,5 @@ export enum DialogsName {
|
|||||||
EstimateExpenseForm = 'estimate-expense-form',
|
EstimateExpenseForm = 'estimate-expense-form',
|
||||||
ProjectInvoicingForm = 'project-invoicing-form',
|
ProjectInvoicingForm = 'project-invoicing-form',
|
||||||
ProjectBillableEntriesForm = 'project-billable-entries',
|
ProjectBillableEntriesForm = 'project-billable-entries',
|
||||||
|
InvoiceNumberSettings = 'InvoiceNumberSettings'
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,30 +4,22 @@ import intl from 'react-intl-universal';
|
|||||||
export const getFooterLinks = () => [
|
export const getFooterLinks = () => [
|
||||||
{
|
{
|
||||||
title: intl.get('blog'),
|
title: intl.get('blog'),
|
||||||
link: '#',
|
link: 'https://docs.bigcapital.ly/blog',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: intl.get('community'),
|
||||||
|
link: 'https://discord.com/invite/c8nPBJafeb',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: intl.get('support'),
|
title: intl.get('support'),
|
||||||
link: '#',
|
link: 'https://discord.com/invite/c8nPBJafeb',
|
||||||
},
|
|
||||||
{
|
|
||||||
title: intl.get('service_status'),
|
|
||||||
link: '#',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: intl.get('pricing'),
|
|
||||||
link: '#',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: intl.get('reseller_partner'),
|
|
||||||
link: '#',
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: intl.get('docs'),
|
title: intl.get('docs'),
|
||||||
link: '#',
|
link: 'https://docs.bigcapital.ly',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'Bigcapital',
|
title: 'Bigcapital',
|
||||||
link: 'http://bigcapital.ly',
|
link: 'http://bigcapital.ly',
|
||||||
}
|
},
|
||||||
]
|
];
|
||||||
|
|||||||
@@ -1,193 +0,0 @@
|
|||||||
// @ts-nocheck
|
|
||||||
import React from 'react';
|
|
||||||
import {
|
|
||||||
Intent,
|
|
||||||
Button,
|
|
||||||
ButtonGroup,
|
|
||||||
Popover,
|
|
||||||
PopoverInteractionKind,
|
|
||||||
Position,
|
|
||||||
Menu,
|
|
||||||
MenuItem,
|
|
||||||
} from '@blueprintjs/core';
|
|
||||||
import classNames from 'classnames';
|
|
||||||
import { useFormikContext } from 'formik';
|
|
||||||
import { FormattedMessage as T, If, Icon } from '@/components';
|
|
||||||
import { CLASSES } from '@/constants/classes';
|
|
||||||
import { useMakeJournalFormContext } from './MakeJournalProvider';
|
|
||||||
import { useHistory } from 'react-router-dom';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Make Journal floating actions bar.
|
|
||||||
*/
|
|
||||||
export default function MakeJournalEntriesFooter() {
|
|
||||||
const history = useHistory();
|
|
||||||
|
|
||||||
// Formik context.
|
|
||||||
const { isSubmitting, submitForm } = useFormikContext();
|
|
||||||
|
|
||||||
// Make journal form context.
|
|
||||||
const {
|
|
||||||
manualJournalId,
|
|
||||||
setSubmitPayload,
|
|
||||||
manualJournalPublished = false,
|
|
||||||
} = useMakeJournalFormContext();
|
|
||||||
|
|
||||||
// Handle `submit & publish` button click.
|
|
||||||
const handleSubmitPublishBtnClick = (event) => {
|
|
||||||
setSubmitPayload({ redirect: true, publish: true });
|
|
||||||
submitForm();
|
|
||||||
};
|
|
||||||
|
|
||||||
// Handle `submit, publish & new` button click.
|
|
||||||
const handleSubmitPublishAndNewBtnClick = (event) => {
|
|
||||||
setSubmitPayload({ redirect: false, publish: true, resetForm: true });
|
|
||||||
submitForm();
|
|
||||||
};
|
|
||||||
|
|
||||||
// Handle `submit, publish & continue editing` button click.
|
|
||||||
const handleSubmitPublishContinueEditingBtnClick = (event) => {
|
|
||||||
setSubmitPayload({ redirect: false, publish: true });
|
|
||||||
submitForm();
|
|
||||||
};
|
|
||||||
|
|
||||||
// Handle `submit as draft` button click.
|
|
||||||
const handleSubmitDraftBtnClick = (event) => {
|
|
||||||
setSubmitPayload({ redirect: true, publish: false });
|
|
||||||
};
|
|
||||||
|
|
||||||
// Handle `submit as draft & new` button click.
|
|
||||||
const handleSubmitDraftAndNewBtnClick = (event) => {
|
|
||||||
setSubmitPayload({ redirect: false, publish: false, resetForm: true });
|
|
||||||
submitForm();
|
|
||||||
};
|
|
||||||
|
|
||||||
// Handles submit as draft & continue editing button click.
|
|
||||||
const handleSubmitDraftContinueEditingBtnClick = (event) => {
|
|
||||||
setSubmitPayload({ redirect: false, publish: false });
|
|
||||||
submitForm();
|
|
||||||
};
|
|
||||||
|
|
||||||
// Handle cancel button action click.
|
|
||||||
const handleCancelBtnClick = (event) => {
|
|
||||||
history.goBack();
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleClearBtnClick = (event) => {};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className={classNames(CLASSES.PAGE_FORM_FLOATING_ACTIONS)}>
|
|
||||||
{/* ----------- Save And Publish ----------- */}
|
|
||||||
<If condition={!manualJournalId || !manualJournalPublished}>
|
|
||||||
<ButtonGroup>
|
|
||||||
<Button
|
|
||||||
disabled={isSubmitting}
|
|
||||||
intent={Intent.PRIMARY}
|
|
||||||
type="submit"
|
|
||||||
onClick={handleSubmitPublishBtnClick}
|
|
||||||
text={<T id={'save_publish'} />}
|
|
||||||
/>
|
|
||||||
<Popover
|
|
||||||
content={
|
|
||||||
<Menu>
|
|
||||||
<MenuItem
|
|
||||||
text={<T id={'publish_and_new'} />}
|
|
||||||
onClick={handleSubmitPublishAndNewBtnClick}
|
|
||||||
/>
|
|
||||||
<MenuItem
|
|
||||||
text={<T id={'publish_continue_editing'} />}
|
|
||||||
onClick={handleSubmitPublishContinueEditingBtnClick}
|
|
||||||
/>
|
|
||||||
</Menu>
|
|
||||||
}
|
|
||||||
minimal={true}
|
|
||||||
interactionKind={PopoverInteractionKind.CLICK}
|
|
||||||
position={Position.BOTTOM_LEFT}
|
|
||||||
>
|
|
||||||
<Button
|
|
||||||
disabled={isSubmitting}
|
|
||||||
intent={Intent.PRIMARY}
|
|
||||||
rightIcon={<Icon icon="arrow-drop-up-16" iconSize={20} />}
|
|
||||||
/>
|
|
||||||
</Popover>
|
|
||||||
</ButtonGroup>
|
|
||||||
{/* ----------- Save As Draft ----------- */}
|
|
||||||
<ButtonGroup>
|
|
||||||
<Button
|
|
||||||
disabled={isSubmitting}
|
|
||||||
className={'ml1'}
|
|
||||||
type="submit"
|
|
||||||
onClick={handleSubmitDraftBtnClick}
|
|
||||||
text={<T id={'save_as_draft'} />}
|
|
||||||
/>
|
|
||||||
<Popover
|
|
||||||
content={
|
|
||||||
<Menu>
|
|
||||||
<MenuItem
|
|
||||||
text={<T id={'save_and_new'} />}
|
|
||||||
onClick={handleSubmitDraftAndNewBtnClick}
|
|
||||||
/>
|
|
||||||
<MenuItem
|
|
||||||
text={<T id={'save_continue_editing'} />}
|
|
||||||
onClick={handleSubmitDraftContinueEditingBtnClick}
|
|
||||||
/>
|
|
||||||
</Menu>
|
|
||||||
}
|
|
||||||
minimal={true}
|
|
||||||
interactionKind={PopoverInteractionKind.CLICK}
|
|
||||||
position={Position.BOTTOM_LEFT}
|
|
||||||
>
|
|
||||||
<Button
|
|
||||||
disabled={isSubmitting}
|
|
||||||
rightIcon={<Icon icon="arrow-drop-up-16" iconSize={20} />}
|
|
||||||
/>
|
|
||||||
</Popover>
|
|
||||||
</ButtonGroup>
|
|
||||||
</If>
|
|
||||||
{/* ----------- Save and New ----------- */}
|
|
||||||
<If condition={manualJournalId && manualJournalPublished}>
|
|
||||||
<ButtonGroup>
|
|
||||||
<Button
|
|
||||||
disabled={isSubmitting}
|
|
||||||
intent={Intent.PRIMARY}
|
|
||||||
type="submit"
|
|
||||||
onClick={handleSubmitPublishBtnClick}
|
|
||||||
text={<T id={'save'} />}
|
|
||||||
/>
|
|
||||||
<Popover
|
|
||||||
content={
|
|
||||||
<Menu>
|
|
||||||
<MenuItem
|
|
||||||
text={<T id={'save_and_new'} />}
|
|
||||||
onClick={handleSubmitPublishAndNewBtnClick}
|
|
||||||
/>
|
|
||||||
</Menu>
|
|
||||||
}
|
|
||||||
minimal={true}
|
|
||||||
interactionKind={PopoverInteractionKind.CLICK}
|
|
||||||
position={Position.BOTTOM_LEFT}
|
|
||||||
>
|
|
||||||
<Button
|
|
||||||
disabled={isSubmitting}
|
|
||||||
intent={Intent.PRIMARY}
|
|
||||||
rightIcon={<Icon icon="arrow-drop-up-16" iconSize={20} />}
|
|
||||||
/>
|
|
||||||
</Popover>
|
|
||||||
</ButtonGroup>
|
|
||||||
</If>
|
|
||||||
{/* ----------- Clear & Reset----------- */}
|
|
||||||
<Button
|
|
||||||
className={'ml1'}
|
|
||||||
disabled={isSubmitting}
|
|
||||||
onClick={handleClearBtnClick}
|
|
||||||
text={manualJournalId ? <T id={'reset'} /> : <T id={'clear'} />}
|
|
||||||
/>
|
|
||||||
{/* ----------- Cancel ----------- */}
|
|
||||||
<Button
|
|
||||||
className={'ml1'}
|
|
||||||
onClick={handleCancelBtnClick}
|
|
||||||
text={<T id={'cancel'} />}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
@@ -4,7 +4,7 @@ import { Formik, Form } from 'formik';
|
|||||||
import { Intent } from '@blueprintjs/core';
|
import { Intent } from '@blueprintjs/core';
|
||||||
import intl from 'react-intl-universal';
|
import intl from 'react-intl-universal';
|
||||||
import * as R from 'ramda';
|
import * as R from 'ramda';
|
||||||
import { defaultTo, isEmpty, omit } from 'lodash';
|
import { isEmpty, omit } from 'lodash';
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import { useHistory } from 'react-router-dom';
|
import { useHistory } from 'react-router-dom';
|
||||||
|
|
||||||
@@ -31,6 +31,7 @@ import {
|
|||||||
transformToEditForm,
|
transformToEditForm,
|
||||||
defaultManualJournal,
|
defaultManualJournal,
|
||||||
} from './utils';
|
} from './utils';
|
||||||
|
import { JournalSyncIncrementSettingsToForm } from './components';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Journal entries form.
|
* Journal entries form.
|
||||||
@@ -40,6 +41,7 @@ function MakeJournalEntriesForm({
|
|||||||
journalNextNumber,
|
journalNextNumber,
|
||||||
journalNumberPrefix,
|
journalNumberPrefix,
|
||||||
journalAutoIncrement,
|
journalAutoIncrement,
|
||||||
|
|
||||||
// #withCurrentOrganization
|
// #withCurrentOrganization
|
||||||
organization: { base_currency },
|
organization: { base_currency },
|
||||||
}) {
|
}) {
|
||||||
@@ -69,6 +71,8 @@ function MakeJournalEntriesForm({
|
|||||||
}
|
}
|
||||||
: {
|
: {
|
||||||
...defaultManualJournal,
|
...defaultManualJournal,
|
||||||
|
// If the auto-increment mode is enabled, take the next journal
|
||||||
|
// number from the settings.
|
||||||
...(journalAutoIncrement && {
|
...(journalAutoIncrement && {
|
||||||
journal_number: journalNumber,
|
journal_number: journalNumber,
|
||||||
}),
|
}),
|
||||||
@@ -116,7 +120,6 @@ function MakeJournalEntriesForm({
|
|||||||
entries: R.compose(orderingLinesIndexes)(entries),
|
entries: R.compose(orderingLinesIndexes)(entries),
|
||||||
publish: submitPayload.publish,
|
publish: submitPayload.publish,
|
||||||
};
|
};
|
||||||
|
|
||||||
// Handle the request error.
|
// Handle the request error.
|
||||||
const handleError = ({
|
const handleError = ({
|
||||||
response: {
|
response: {
|
||||||
@@ -126,7 +129,6 @@ function MakeJournalEntriesForm({
|
|||||||
transformErrors(errors, { setErrors });
|
transformErrors(errors, { setErrors });
|
||||||
setSubmitting(false);
|
setSubmitting(false);
|
||||||
};
|
};
|
||||||
|
|
||||||
// Handle the request success.
|
// Handle the request success.
|
||||||
const handleSuccess = (errors) => {
|
const handleSuccess = (errors) => {
|
||||||
AppToaster.show({
|
AppToaster.show({
|
||||||
@@ -147,7 +149,6 @@ function MakeJournalEntriesForm({
|
|||||||
resetForm();
|
resetForm();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
if (isNewMode) {
|
if (isNewMode) {
|
||||||
createJournalMutate(form).then(handleSuccess).catch(handleError);
|
createJournalMutate(form).then(handleSuccess).catch(handleError);
|
||||||
} else {
|
} else {
|
||||||
@@ -179,6 +180,9 @@ function MakeJournalEntriesForm({
|
|||||||
|
|
||||||
{/* --------- Dialogs --------- */}
|
{/* --------- Dialogs --------- */}
|
||||||
<MakeJournalFormDialogs />
|
<MakeJournalFormDialogs />
|
||||||
|
|
||||||
|
{/* --------- Effects --------- */}
|
||||||
|
<JournalSyncIncrementSettingsToForm />
|
||||||
</Form>
|
</Form>
|
||||||
</Formik>
|
</Formik>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -8,6 +8,19 @@ import { PageFormBigNumber, FormattedMessage as T } from '@/components';
|
|||||||
import MakeJournalEntriesHeaderFields from './MakeJournalEntriesHeaderFields';
|
import MakeJournalEntriesHeaderFields from './MakeJournalEntriesHeaderFields';
|
||||||
|
|
||||||
export default function MakeJournalEntriesHeader() {
|
export default function MakeJournalEntriesHeader() {
|
||||||
|
return (
|
||||||
|
<div className={classNames(CLASSES.PAGE_FORM_HEADER)}>
|
||||||
|
<MakeJournalEntriesHeaderFields />
|
||||||
|
<MakeJournalHeaderBigNumber />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Big total number of make journal header.
|
||||||
|
* @returns {React.ReactNode}
|
||||||
|
*/
|
||||||
|
function MakeJournalHeaderBigNumber() {
|
||||||
const {
|
const {
|
||||||
values: { entries, currency_code },
|
values: { entries, currency_code },
|
||||||
} = useFormikContext();
|
} = useFormikContext();
|
||||||
@@ -17,14 +30,10 @@ export default function MakeJournalEntriesHeader() {
|
|||||||
const total = Math.max(totalCredit, totalDebit);
|
const total = Math.max(totalCredit, totalDebit);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={classNames(CLASSES.PAGE_FORM_HEADER)}>
|
<PageFormBigNumber
|
||||||
<MakeJournalEntriesHeaderFields />
|
label={<T id={'amount'} />}
|
||||||
|
amount={total}
|
||||||
<PageFormBigNumber
|
currencyCode={currency_code}
|
||||||
label={<T id={'amount'} />}
|
/>
|
||||||
amount={total}
|
|
||||||
currencyCode={currency_code}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,14 +6,14 @@ import {
|
|||||||
Position,
|
Position,
|
||||||
ControlGroup,
|
ControlGroup,
|
||||||
} from '@blueprintjs/core';
|
} from '@blueprintjs/core';
|
||||||
import { FastField, ErrorMessage } from 'formik';
|
import { FastField, ErrorMessage, useFormikContext } from 'formik';
|
||||||
import { DateInput } from '@blueprintjs/datetime';
|
import { DateInput } from '@blueprintjs/datetime';
|
||||||
|
import * as R from 'ramda';
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
|
|
||||||
import { CLASSES } from '@/constants/classes';
|
import { CLASSES } from '@/constants/classes';
|
||||||
import {
|
import {
|
||||||
momentFormatter,
|
momentFormatter,
|
||||||
compose,
|
|
||||||
inputIntent,
|
inputIntent,
|
||||||
handleDateChange,
|
handleDateChange,
|
||||||
tansformDateValue,
|
tansformDateValue,
|
||||||
@@ -25,54 +25,101 @@ import {
|
|||||||
Icon,
|
Icon,
|
||||||
InputPrependButton,
|
InputPrependButton,
|
||||||
CurrencySelectList,
|
CurrencySelectList,
|
||||||
FormattedMessage as T
|
FormattedMessage as T,
|
||||||
|
FInputGroup,
|
||||||
|
FFormGroup,
|
||||||
} from '@/components';
|
} from '@/components';
|
||||||
import { useMakeJournalFormContext } from './MakeJournalProvider';
|
import { useMakeJournalFormContext } from './MakeJournalProvider';
|
||||||
import { JournalExchangeRateInputField } from './components';
|
import { JournalExchangeRateInputField } from './components';
|
||||||
|
import { currenciesFieldShouldUpdate } from './utils';
|
||||||
|
|
||||||
import withSettings from '@/containers/Settings/withSettings';
|
import withSettings from '@/containers/Settings/withSettings';
|
||||||
import withDialogActions from '@/containers/Dialog/withDialogActions';
|
import withDialogActions from '@/containers/Dialog/withDialogActions';
|
||||||
import {
|
|
||||||
currenciesFieldShouldUpdate,
|
/**
|
||||||
useObserveJournalNoSettings,
|
* Journal number field of make journal form.
|
||||||
} from './utils';
|
*/
|
||||||
|
const MakeJournalTransactionNoField = R.compose(
|
||||||
|
withDialogActions,
|
||||||
|
withSettings(({ manualJournalsSettings }) => ({
|
||||||
|
journalAutoIncrement: manualJournalsSettings?.autoIncrement,
|
||||||
|
})),
|
||||||
|
)(
|
||||||
|
({
|
||||||
|
// #withDialog
|
||||||
|
openDialog,
|
||||||
|
|
||||||
|
// #withSettings
|
||||||
|
journalAutoIncrement,
|
||||||
|
}) => {
|
||||||
|
const { setFieldValue, values } = useFormikContext();
|
||||||
|
|
||||||
|
const handleJournalNumberChange = () => {
|
||||||
|
openDialog('journal-number-form');
|
||||||
|
};
|
||||||
|
const handleJournalNoBlur = (event) => {
|
||||||
|
const newValue = event.target.value;
|
||||||
|
|
||||||
|
if (values.journal_number !== newValue && journalAutoIncrement) {
|
||||||
|
openDialog('journal-number-form', {
|
||||||
|
initialFormValues: {
|
||||||
|
onceManualNumber: newValue,
|
||||||
|
incrementMode: 'manual-transaction',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (!journalAutoIncrement) {
|
||||||
|
setFieldValue('journal_number', newValue);
|
||||||
|
setFieldValue('journal_number_manually', newValue);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<FFormGroup
|
||||||
|
name={'journal_number'}
|
||||||
|
label={<T id={'journal_no'} />}
|
||||||
|
labelInfo={
|
||||||
|
<>
|
||||||
|
<FieldRequiredHint />
|
||||||
|
<FieldHint />
|
||||||
|
</>
|
||||||
|
}
|
||||||
|
fill={true}
|
||||||
|
inline={true}
|
||||||
|
fastField={true}
|
||||||
|
>
|
||||||
|
<ControlGroup fill={true}>
|
||||||
|
<FInputGroup
|
||||||
|
name={'journal_number'}
|
||||||
|
fill={true}
|
||||||
|
asyncControl={true}
|
||||||
|
onBlur={handleJournalNoBlur}
|
||||||
|
fastField={true}
|
||||||
|
onChange={() => {}}
|
||||||
|
/>
|
||||||
|
<InputPrependButton
|
||||||
|
buttonProps={{
|
||||||
|
onClick: handleJournalNumberChange,
|
||||||
|
icon: <Icon icon={'settings-18'} />,
|
||||||
|
}}
|
||||||
|
tooltip={true}
|
||||||
|
tooltipProps={{
|
||||||
|
content: <T id={'setting_your_auto_generated_journal_number'} />,
|
||||||
|
position: Position.BOTTOM_LEFT,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</ControlGroup>
|
||||||
|
</FFormGroup>
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Make journal entries header.
|
* Make journal entries header.
|
||||||
*/
|
*/
|
||||||
function MakeJournalEntriesHeader({
|
export default function MakeJournalEntriesHeader({}) {
|
||||||
// #ownProps
|
|
||||||
onJournalNumberChanged,
|
|
||||||
|
|
||||||
// #withDialog
|
|
||||||
openDialog,
|
|
||||||
|
|
||||||
// #withSettings
|
|
||||||
journalAutoIncrement,
|
|
||||||
journalNextNumber,
|
|
||||||
journalNumberPrefix,
|
|
||||||
}) {
|
|
||||||
const { currencies } = useMakeJournalFormContext();
|
const { currencies } = useMakeJournalFormContext();
|
||||||
|
|
||||||
// Handle journal number change.
|
|
||||||
const handleJournalNumberChange = () => {
|
|
||||||
openDialog('journal-number-form');
|
|
||||||
};
|
|
||||||
|
|
||||||
// Handle journal number blur.
|
|
||||||
const handleJournalNoBlur = (form, field) => (event) => {
|
|
||||||
const newValue = event.target.value;
|
|
||||||
|
|
||||||
if (field.value !== newValue && journalAutoIncrement) {
|
|
||||||
openDialog('journal-number-form', {
|
|
||||||
initialFormValues: {
|
|
||||||
manualTransactionNo: newValue,
|
|
||||||
incrementMode: 'manual-transaction',
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
useObserveJournalNoSettings(journalNumberPrefix, journalNextNumber);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={classNames(CLASSES.PAGE_FORM_HEADER_FIELDS)}>
|
<div className={classNames(CLASSES.PAGE_FORM_HEADER_FIELDS)}>
|
||||||
{/*------------ Posting date -----------*/}
|
{/*------------ Posting date -----------*/}
|
||||||
@@ -106,46 +153,7 @@ function MakeJournalEntriesHeader({
|
|||||||
</FastField>
|
</FastField>
|
||||||
|
|
||||||
{/*------------ Journal number -----------*/}
|
{/*------------ Journal number -----------*/}
|
||||||
<FastField name={'journal_number'}>
|
<MakeJournalTransactionNoField />
|
||||||
{({ form, field, meta: { error, touched } }) => (
|
|
||||||
<FormGroup
|
|
||||||
label={<T id={'journal_no'} />}
|
|
||||||
labelInfo={
|
|
||||||
<>
|
|
||||||
<FieldRequiredHint />
|
|
||||||
<FieldHint />
|
|
||||||
</>
|
|
||||||
}
|
|
||||||
className={'form-group--journal-number'}
|
|
||||||
intent={inputIntent({ error, touched })}
|
|
||||||
helperText={<ErrorMessage name="journal_number" />}
|
|
||||||
fill={true}
|
|
||||||
inline={true}
|
|
||||||
>
|
|
||||||
<ControlGroup fill={true}>
|
|
||||||
<InputGroup
|
|
||||||
fill={true}
|
|
||||||
value={field.value}
|
|
||||||
asyncControl={true}
|
|
||||||
onBlur={handleJournalNoBlur(form, field)}
|
|
||||||
/>
|
|
||||||
<InputPrependButton
|
|
||||||
buttonProps={{
|
|
||||||
onClick: handleJournalNumberChange,
|
|
||||||
icon: <Icon icon={'settings-18'} />,
|
|
||||||
}}
|
|
||||||
tooltip={true}
|
|
||||||
tooltipProps={{
|
|
||||||
content: (
|
|
||||||
<T id={'setting_your_auto_generated_journal_number'} />
|
|
||||||
),
|
|
||||||
position: Position.BOTTOM_LEFT,
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</ControlGroup>
|
|
||||||
</FormGroup>
|
|
||||||
)}
|
|
||||||
</FastField>
|
|
||||||
|
|
||||||
{/*------------ Reference -----------*/}
|
{/*------------ Reference -----------*/}
|
||||||
<FastField name={'reference'}>
|
<FastField name={'reference'}>
|
||||||
@@ -219,12 +227,3 @@ function MakeJournalEntriesHeader({
|
|||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export default compose(
|
|
||||||
withDialogActions,
|
|
||||||
withSettings(({ manualJournalsSettings }) => ({
|
|
||||||
journalAutoIncrement: manualJournalsSettings?.autoIncrement,
|
|
||||||
journalNextNumber: manualJournalsSettings?.nextNumber,
|
|
||||||
journalNumberPrefix: manualJournalsSettings?.numberPrefix,
|
|
||||||
})),
|
|
||||||
)(MakeJournalEntriesHeader);
|
|
||||||
|
|||||||
@@ -10,17 +10,21 @@ export default function MakeJournalFormDialogs() {
|
|||||||
const { setFieldValue } = useFormikContext();
|
const { setFieldValue } = useFormikContext();
|
||||||
|
|
||||||
// Update the form once the journal number form submit confirm.
|
// Update the form once the journal number form submit confirm.
|
||||||
const handleConfirm = ({ manually, incrementNumber }) => {
|
const handleConfirm = (settings) => {
|
||||||
setFieldValue('journal_number', incrementNumber || '');
|
// Set the invoice transaction no. that cames from dialog to the form.
|
||||||
setFieldValue('journal_number_manually', manually);
|
// the `journal_number` will be empty except the increment mode is not auto.
|
||||||
|
setFieldValue('journal_number', settings.transactionNumber);
|
||||||
|
setFieldValue('journal_number_manually', '');
|
||||||
|
|
||||||
|
if (settings.incrementMode !== 'auto') {
|
||||||
|
setFieldValue('journal_number_manually', settings.transactionNumber);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<JournalNumberDialog
|
||||||
<JournalNumberDialog
|
dialogName={'journal-number-form'}
|
||||||
dialogName={'journal-number-form'}
|
onConfirm={handleConfirm}
|
||||||
onConfirm={handleConfirm}
|
/>
|
||||||
/>
|
|
||||||
</>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,9 +1,10 @@
|
|||||||
// @ts-nocheck
|
// @ts-nocheck
|
||||||
import React from 'react';
|
import React, { useEffect } from 'react';
|
||||||
import intl from 'react-intl-universal';
|
import intl from 'react-intl-universal';
|
||||||
import { Menu, MenuItem, Position, Button } from '@blueprintjs/core';
|
import { Menu, MenuItem, Position, Button } from '@blueprintjs/core';
|
||||||
import { Popover2 } from '@blueprintjs/popover2';
|
import { Popover2 } from '@blueprintjs/popover2';
|
||||||
import { useFormikContext } from 'formik';
|
import { useFormikContext } from 'formik';
|
||||||
|
import * as R from 'ramda';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
ExchangeRateInputGroup,
|
ExchangeRateInputGroup,
|
||||||
@@ -24,6 +25,9 @@ import { CellType, Features, Align } from '@/constants';
|
|||||||
|
|
||||||
import { useCurrentOrganization, useFeatureCan } from '@/hooks/state';
|
import { useCurrentOrganization, useFeatureCan } from '@/hooks/state';
|
||||||
import { useJournalIsForeign } from './utils';
|
import { useJournalIsForeign } from './utils';
|
||||||
|
import withSettings from '@/containers/Settings/withSettings';
|
||||||
|
import { transactionNumber } from '@/utils';
|
||||||
|
import { useUpdateEffect } from '@/hooks';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Contact header cell.
|
* Contact header cell.
|
||||||
@@ -199,3 +203,37 @@ export function JournalExchangeRateInputField({ ...props }) {
|
|||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Syncs journal auto-increment settings to form.
|
||||||
|
* @return {React.ReactNode}
|
||||||
|
*/
|
||||||
|
export const JournalSyncIncrementSettingsToForm = R.compose(
|
||||||
|
withSettings(({ manualJournalsSettings }) => ({
|
||||||
|
journalAutoIncrement: manualJournalsSettings?.autoIncrement,
|
||||||
|
journalNextNumber: manualJournalsSettings?.nextNumber,
|
||||||
|
journalNumberPrefix: manualJournalsSettings?.numberPrefix,
|
||||||
|
})),
|
||||||
|
)(({ journalAutoIncrement, journalNextNumber, journalNumberPrefix }) => {
|
||||||
|
const { setFieldValue } = useFormikContext();
|
||||||
|
|
||||||
|
useUpdateEffect(() => {
|
||||||
|
// Do not update if the journal auto-increment mode is disabled.
|
||||||
|
if (!journalAutoIncrement) return null;
|
||||||
|
|
||||||
|
setFieldValue(
|
||||||
|
'journal_number',
|
||||||
|
transactionNumber(journalNumberPrefix, journalNextNumber),
|
||||||
|
);
|
||||||
|
}, [
|
||||||
|
setFieldValue,
|
||||||
|
journalNumberPrefix,
|
||||||
|
journalNextNumber,
|
||||||
|
journalAutoIncrement,
|
||||||
|
]);
|
||||||
|
|
||||||
|
return null;
|
||||||
|
});
|
||||||
|
|
||||||
|
JournalSyncIncrementSettingsToForm.displayName =
|
||||||
|
'JournalSyncIncrementSettingsToForm';
|
||||||
|
|||||||
@@ -6,7 +6,6 @@ import intl from 'react-intl-universal';
|
|||||||
import { Intent } from '@blueprintjs/core';
|
import { Intent } from '@blueprintjs/core';
|
||||||
import { sumBy, setWith, toSafeInteger, get, first } from 'lodash';
|
import { sumBy, setWith, toSafeInteger, get, first } from 'lodash';
|
||||||
import {
|
import {
|
||||||
transactionNumber,
|
|
||||||
updateTableCell,
|
updateTableCell,
|
||||||
repeatValue,
|
repeatValue,
|
||||||
transformToForm,
|
transformToForm,
|
||||||
@@ -29,6 +28,8 @@ const ERROR = {
|
|||||||
CREDIT_DEBIT_SUMATION_SHOULD_NOT_EQUAL_ZERO:
|
CREDIT_DEBIT_SUMATION_SHOULD_NOT_EQUAL_ZERO:
|
||||||
'CREDIT.DEBIT.SUMATION.SHOULD.NOT.EQUAL.ZERO',
|
'CREDIT.DEBIT.SUMATION.SHOULD.NOT.EQUAL.ZERO',
|
||||||
ENTRIES_SHOULD_ASSIGN_WITH_CONTACT: 'ENTRIES_SHOULD_ASSIGN_WITH_CONTACT',
|
ENTRIES_SHOULD_ASSIGN_WITH_CONTACT: 'ENTRIES_SHOULD_ASSIGN_WITH_CONTACT',
|
||||||
|
COULD_NOT_ASSIGN_DIFFERENT_CURRENCY_TO_ACCOUNTS:
|
||||||
|
'COULD_NOT_ASSIGN_DIFFERENT_CURRENCY_TO_ACCOUNTS',
|
||||||
};
|
};
|
||||||
|
|
||||||
export const MIN_LINES_NUMBER = 1;
|
export const MIN_LINES_NUMBER = 1;
|
||||||
@@ -46,7 +47,7 @@ export const defaultEntry = {
|
|||||||
|
|
||||||
export const defaultManualJournal = {
|
export const defaultManualJournal = {
|
||||||
journal_number: '',
|
journal_number: '',
|
||||||
journal_number_manually: false,
|
journal_number_manually: '',
|
||||||
journal_type: 'Journal',
|
journal_type: 'Journal',
|
||||||
date: moment(new Date()).format('YYYY-MM-DD'),
|
date: moment(new Date()).format('YYYY-MM-DD'),
|
||||||
description: '',
|
description: '',
|
||||||
@@ -162,6 +163,15 @@ export const transformErrors = (resErrors, { setErrors, errors }) => {
|
|||||||
intl.get('journal_number_is_already_used'),
|
intl.get('journal_number_is_already_used'),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
if (
|
||||||
|
(error = getError(ERROR.COULD_NOT_ASSIGN_DIFFERENT_CURRENCY_TO_ACCOUNTS))
|
||||||
|
) {
|
||||||
|
toastMessages.push(
|
||||||
|
intl.get(
|
||||||
|
'make_journal.errors.should_add_accounts_in_same_currency_or_base_currency',
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
setErrors({ ...newErrors });
|
setErrors({ ...newErrors });
|
||||||
|
|
||||||
if (toastMessages.length > 0) {
|
if (toastMessages.length > 0) {
|
||||||
@@ -174,15 +184,6 @@ export const transformErrors = (resErrors, { setErrors, errors }) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
export const useObserveJournalNoSettings = (prefix, nextNumber) => {
|
|
||||||
const { setFieldValue } = useFormikContext();
|
|
||||||
|
|
||||||
React.useEffect(() => {
|
|
||||||
const journalNo = transactionNumber(prefix, nextNumber);
|
|
||||||
setFieldValue('journal_number', journalNo);
|
|
||||||
}, [setFieldValue, prefix, nextNumber]);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Detarmines entries fast field should update.
|
* Detarmines entries fast field should update.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -1,9 +1,15 @@
|
|||||||
// @ts-nocheck
|
// @ts-nocheck
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
|
||||||
import OwnerContributionFormFields from './OwnerContribution/OwnerContributionFormFields';
|
import OwnerContributionFormFields from './OwnerContribution/OwnerContributionFormFields';
|
||||||
import OtherIncomeFormFields from './OtherIncome/OtherIncomeFormFields';
|
import OtherIncomeFormFields from './OtherIncome/OtherIncomeFormFields';
|
||||||
import TransferFromAccountFormFields from './TransferFromAccount/TransferFromAccountFormFields';
|
import TransferFromAccountFormFields from './TransferFromAccount/TransferFromAccountFormFields';
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param param0
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
export default function MoneyInContentFields({ accountType }) {
|
export default function MoneyInContentFields({ accountType }) {
|
||||||
const handleTransactionType = () => {
|
const handleTransactionType = () => {
|
||||||
switch (accountType) {
|
switch (accountType) {
|
||||||
@@ -19,6 +25,5 @@ export default function MoneyInContentFields({ accountType }) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
return <React.Fragment>{handleTransactionType()}</React.Fragment>;
|
return <React.Fragment>{handleTransactionType()}</React.Fragment>;
|
||||||
}
|
}
|
||||||
@@ -27,13 +27,10 @@ function MoneyInFloatingActions({
|
|||||||
setSubmitPayload({ publish: false });
|
setSubmitPayload({ publish: false });
|
||||||
submitForm();
|
submitForm();
|
||||||
};
|
};
|
||||||
|
|
||||||
// Handle submit button click.
|
// Handle submit button click.
|
||||||
const handleSubmittBtnClick = (event) => {
|
const handleSubmittBtnClick = (event) => {
|
||||||
setSubmitPayload({ publish: true });
|
setSubmitPayload({ publish: true });
|
||||||
submitForm();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Handle close button click.
|
// Handle close button click.
|
||||||
const handleCloseBtnClick = (event) => {
|
const handleCloseBtnClick = (event) => {
|
||||||
closeDialog(dialogName);
|
closeDialog(dialogName);
|
||||||
@@ -5,6 +5,7 @@ import { Form } from 'formik';
|
|||||||
import MoneyInFormFields from './MoneyInFormFields';
|
import MoneyInFormFields from './MoneyInFormFields';
|
||||||
import MoneyInFormDialog from './MoneyInFormDialog';
|
import MoneyInFormDialog from './MoneyInFormDialog';
|
||||||
import MoneyInFloatingActions from './MoneyInFloatingActions';
|
import MoneyInFloatingActions from './MoneyInFloatingActions';
|
||||||
|
import { MoneyInOutSyncIncrementSettingsToForm } from '../_components';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Money In form content.
|
* Money In form content.
|
||||||
@@ -15,6 +16,7 @@ export default function MoneyInFormContent() {
|
|||||||
<MoneyInFormFields />
|
<MoneyInFormFields />
|
||||||
<MoneyInFormDialog />
|
<MoneyInFormDialog />
|
||||||
<MoneyInFloatingActions />
|
<MoneyInFloatingActions />
|
||||||
|
<MoneyInOutSyncIncrementSettingsToForm />
|
||||||
</Form>
|
</Form>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -11,12 +11,9 @@ export default function MoneyInFormDialog() {
|
|||||||
const { setFieldValue } = useFormikContext();
|
const { setFieldValue } = useFormikContext();
|
||||||
|
|
||||||
// Update the form once the transaction number form submit confirm.
|
// Update the form once the transaction number form submit confirm.
|
||||||
const handleTransactionNumberFormConfirm = ({
|
const handleTransactionNumberFormConfirm = (settings) => {
|
||||||
incrementNumber,
|
setFieldValue('transaction_number', settings.transactionNumber);
|
||||||
manually,
|
setFieldValue('transaction_number_manually', settings.transactionNumber);
|
||||||
}) => {
|
|
||||||
setFieldValue('transaction_number', incrementNumber || '');
|
|
||||||
setFieldValue('transaction_number_manually', manually);
|
|
||||||
};
|
};
|
||||||
return (
|
return (
|
||||||
<React.Fragment>
|
<React.Fragment>
|
||||||
@@ -16,14 +16,12 @@ import {
|
|||||||
InputPrependText,
|
InputPrependText,
|
||||||
MoneyInputGroup,
|
MoneyInputGroup,
|
||||||
FieldRequiredHint,
|
FieldRequiredHint,
|
||||||
Icon,
|
|
||||||
Col,
|
Col,
|
||||||
Row,
|
Row,
|
||||||
If,
|
If,
|
||||||
FeatureCan,
|
FeatureCan,
|
||||||
BranchSelect,
|
BranchSelect,
|
||||||
BranchSelectButton,
|
BranchSelectButton,
|
||||||
InputPrependButton,
|
|
||||||
ExchangeRateMutedField,
|
ExchangeRateMutedField,
|
||||||
} from '@/components';
|
} from '@/components';
|
||||||
import { DateInput } from '@blueprintjs/datetime';
|
import { DateInput } from '@blueprintjs/datetime';
|
||||||
@@ -35,65 +33,26 @@ import {
|
|||||||
momentFormatter,
|
momentFormatter,
|
||||||
tansformDateValue,
|
tansformDateValue,
|
||||||
handleDateChange,
|
handleDateChange,
|
||||||
compose,
|
|
||||||
} from '@/utils';
|
} from '@/utils';
|
||||||
|
|
||||||
import { useMoneyInDailogContext } from '../MoneyInDialogProvider';
|
import { useMoneyInDailogContext } from '../MoneyInDialogProvider';
|
||||||
import {
|
import {
|
||||||
useObserveTransactionNoSettings,
|
|
||||||
useSetPrimaryBranchToForm,
|
useSetPrimaryBranchToForm,
|
||||||
useForeignAccount,
|
useForeignAccount,
|
||||||
BranchRowDivider,
|
BranchRowDivider,
|
||||||
} from '../utils';
|
} from '../utils';
|
||||||
import withSettings from '@/containers/Settings/withSettings';
|
import { MoneyInOutTransactionNoField } from '../../_components';
|
||||||
import withDialogActions from '@/containers/Dialog/withDialogActions';
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Other income form fields.
|
* Other income form fields.
|
||||||
*/
|
*/
|
||||||
function OtherIncomeFormFields({
|
export default function OtherIncomeFormFields() {
|
||||||
// #withDialogActions
|
|
||||||
openDialog,
|
|
||||||
|
|
||||||
// #withSettings
|
|
||||||
transactionAutoIncrement,
|
|
||||||
transactionNumberPrefix,
|
|
||||||
transactionNextNumber,
|
|
||||||
}) {
|
|
||||||
// Money in dialog context.
|
// Money in dialog context.
|
||||||
const { accounts, account, branches } = useMoneyInDailogContext();
|
const { accounts, account, branches } = useMoneyInDailogContext();
|
||||||
|
|
||||||
const { values } = useFormikContext();
|
const { values } = useFormikContext();
|
||||||
|
|
||||||
const amountFieldRef = useAutofocus();
|
const amountFieldRef = useAutofocus();
|
||||||
|
|
||||||
const isForeigAccount = useForeignAccount();
|
const isForeigAccount = useForeignAccount();
|
||||||
|
|
||||||
// Handle tranaction number changing.
|
|
||||||
const handleTransactionNumberChange = () => {
|
|
||||||
openDialog('transaction-number-form');
|
|
||||||
};
|
|
||||||
|
|
||||||
// Handle transaction no. field blur.
|
|
||||||
const handleTransactionNoBlur = (form, field) => (event) => {
|
|
||||||
const newValue = event.target.value;
|
|
||||||
|
|
||||||
if (field.value !== newValue && transactionAutoIncrement) {
|
|
||||||
openDialog('transaction-number-form', {
|
|
||||||
initialFormValues: {
|
|
||||||
manualTransactionNo: newValue,
|
|
||||||
incrementMode: 'manual-transaction',
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Syncs transaction number settings with form.
|
|
||||||
useObserveTransactionNoSettings(
|
|
||||||
transactionNumberPrefix,
|
|
||||||
transactionNextNumber,
|
|
||||||
);
|
|
||||||
|
|
||||||
// Sets the primary branch to form.
|
// Sets the primary branch to form.
|
||||||
useSetPrimaryBranchToForm();
|
useSetPrimaryBranchToForm();
|
||||||
|
|
||||||
@@ -149,42 +108,7 @@ function OtherIncomeFormFields({
|
|||||||
</Col>
|
</Col>
|
||||||
<Col xs={5}>
|
<Col xs={5}>
|
||||||
{/*------------ Transaction number -----------*/}
|
{/*------------ Transaction number -----------*/}
|
||||||
<Field name={'transaction_number'}>
|
<MoneyInOutTransactionNoField />
|
||||||
{({ form, field, meta: { error, touched } }) => (
|
|
||||||
<FormGroup
|
|
||||||
label={<T id={'transaction_number'} />}
|
|
||||||
intent={inputIntent({ error, touched })}
|
|
||||||
helperText={<ErrorMessage name="transaction_number" />}
|
|
||||||
className={'form-group--transaction_number'}
|
|
||||||
>
|
|
||||||
<ControlGroup fill={true}>
|
|
||||||
<InputGroup
|
|
||||||
minimal={true}
|
|
||||||
value={field.value}
|
|
||||||
asyncControl={true}
|
|
||||||
onBlur={handleTransactionNoBlur(form, field)}
|
|
||||||
/>
|
|
||||||
<InputPrependButton
|
|
||||||
buttonProps={{
|
|
||||||
onClick: handleTransactionNumberChange,
|
|
||||||
icon: <Icon icon={'settings-18'} />,
|
|
||||||
}}
|
|
||||||
tooltip={true}
|
|
||||||
tooltipProps={{
|
|
||||||
content: (
|
|
||||||
<T
|
|
||||||
id={
|
|
||||||
'cash_flow.setting_your_auto_generated_transaction_number'
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
),
|
|
||||||
position: Position.BOTTOM_LEFT,
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</ControlGroup>
|
|
||||||
</FormGroup>
|
|
||||||
)}
|
|
||||||
</Field>
|
|
||||||
</Col>
|
</Col>
|
||||||
</Row>
|
</Row>
|
||||||
{/*------------ amount -----------*/}
|
{/*------------ amount -----------*/}
|
||||||
@@ -298,12 +222,3 @@ function OtherIncomeFormFields({
|
|||||||
</React.Fragment>
|
</React.Fragment>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export default compose(
|
|
||||||
withDialogActions,
|
|
||||||
withSettings(({ cashflowSetting }) => ({
|
|
||||||
transactionAutoIncrement: cashflowSetting?.autoIncrement,
|
|
||||||
transactionNextNumber: cashflowSetting?.nextNumber,
|
|
||||||
transactionNumberPrefix: cashflowSetting?.numberPrefix,
|
|
||||||
})),
|
|
||||||
)(OtherIncomeFormFields);
|
|
||||||
@@ -17,11 +17,9 @@ import {
|
|||||||
InputPrependText,
|
InputPrependText,
|
||||||
MoneyInputGroup,
|
MoneyInputGroup,
|
||||||
FieldRequiredHint,
|
FieldRequiredHint,
|
||||||
Icon,
|
|
||||||
Col,
|
Col,
|
||||||
Row,
|
Row,
|
||||||
If,
|
If,
|
||||||
InputPrependButton,
|
|
||||||
ExchangeRateMutedField,
|
ExchangeRateMutedField,
|
||||||
BranchSelect,
|
BranchSelect,
|
||||||
BranchSelectButton,
|
BranchSelectButton,
|
||||||
@@ -35,31 +33,20 @@ import {
|
|||||||
momentFormatter,
|
momentFormatter,
|
||||||
tansformDateValue,
|
tansformDateValue,
|
||||||
handleDateChange,
|
handleDateChange,
|
||||||
compose,
|
|
||||||
} from '@/utils';
|
} from '@/utils';
|
||||||
import { useMoneyInDailogContext } from '../MoneyInDialogProvider';
|
import { useMoneyInDailogContext } from '../MoneyInDialogProvider';
|
||||||
import {
|
import {
|
||||||
useObserveTransactionNoSettings,
|
|
||||||
useSetPrimaryBranchToForm,
|
useSetPrimaryBranchToForm,
|
||||||
useForeignAccount,
|
useForeignAccount,
|
||||||
BranchRowDivider,
|
BranchRowDivider,
|
||||||
} from '../../MoneyInDialog/utils';
|
} from '../../MoneyInDialog/utils';
|
||||||
import withSettings from '@/containers/Settings/withSettings';
|
import { MoneyInOutTransactionNoField } from '../../_components';
|
||||||
import withDialogActions from '@/containers/Dialog/withDialogActions';
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
/**
|
/**
|
||||||
* Owner contribution form fields.
|
* Owner contribution form fields.
|
||||||
*/
|
*/
|
||||||
function OwnerContributionFormFields({
|
export default function OwnerContributionFormFields() {
|
||||||
// #withDialogActions
|
|
||||||
openDialog,
|
|
||||||
|
|
||||||
// #withSettings
|
|
||||||
transactionAutoIncrement,
|
|
||||||
transactionNumberPrefix,
|
|
||||||
transactionNextNumber,
|
|
||||||
}) {
|
|
||||||
// Money in dialog context.
|
// Money in dialog context.
|
||||||
const { accounts, account, branches } = useMoneyInDailogContext();
|
const { accounts, account, branches } = useMoneyInDailogContext();
|
||||||
|
|
||||||
@@ -69,31 +56,6 @@ function OwnerContributionFormFields({
|
|||||||
|
|
||||||
const isForeigAccount = useForeignAccount();
|
const isForeigAccount = useForeignAccount();
|
||||||
|
|
||||||
// Handle tranaction number changing.
|
|
||||||
const handleTransactionNumberChange = () => {
|
|
||||||
openDialog('transaction-number-form');
|
|
||||||
};
|
|
||||||
|
|
||||||
// Handle transaction no. field blur.
|
|
||||||
const handleTransactionNoBlur = (form, field) => (event) => {
|
|
||||||
const newValue = event.target.value;
|
|
||||||
|
|
||||||
if (field.value !== newValue && transactionAutoIncrement) {
|
|
||||||
openDialog('transaction-number-form', {
|
|
||||||
initialFormValues: {
|
|
||||||
manualTransactionNo: newValue,
|
|
||||||
incrementMode: 'manual-transaction',
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Syncs transaction number settings with form.
|
|
||||||
useObserveTransactionNoSettings(
|
|
||||||
transactionNumberPrefix,
|
|
||||||
transactionNextNumber,
|
|
||||||
);
|
|
||||||
|
|
||||||
// Sets the primary branch to form.
|
// Sets the primary branch to form.
|
||||||
useSetPrimaryBranchToForm();
|
useSetPrimaryBranchToForm();
|
||||||
|
|
||||||
@@ -148,42 +110,7 @@ function OwnerContributionFormFields({
|
|||||||
</Col>
|
</Col>
|
||||||
<Col xs={5}>
|
<Col xs={5}>
|
||||||
{/*------------ Transaction number -----------*/}
|
{/*------------ Transaction number -----------*/}
|
||||||
<Field name={'transaction_number'}>
|
<MoneyInOutTransactionNoField />
|
||||||
{({ form, field, meta: { error, touched } }) => (
|
|
||||||
<FormGroup
|
|
||||||
label={<T id={'transaction_number'} />}
|
|
||||||
intent={inputIntent({ error, touched })}
|
|
||||||
helperText={<ErrorMessage name="transaction_number" />}
|
|
||||||
className={'form-group--transaction_number'}
|
|
||||||
>
|
|
||||||
<ControlGroup fill={true}>
|
|
||||||
<InputGroup
|
|
||||||
minimal={true}
|
|
||||||
value={field.value}
|
|
||||||
asyncControl={true}
|
|
||||||
onBlur={handleTransactionNoBlur(form, field)}
|
|
||||||
/>
|
|
||||||
<InputPrependButton
|
|
||||||
buttonProps={{
|
|
||||||
onClick: handleTransactionNumberChange,
|
|
||||||
icon: <Icon icon={'settings-18'} />,
|
|
||||||
}}
|
|
||||||
tooltip={true}
|
|
||||||
tooltipProps={{
|
|
||||||
content: (
|
|
||||||
<T
|
|
||||||
id={
|
|
||||||
'cash_flow.setting_your_auto_generated_transaction_number'
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
),
|
|
||||||
position: Position.BOTTOM_LEFT,
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</ControlGroup>
|
|
||||||
</FormGroup>
|
|
||||||
)}
|
|
||||||
</Field>
|
|
||||||
</Col>
|
</Col>
|
||||||
</Row>
|
</Row>
|
||||||
{/*------------ amount -----------*/}
|
{/*------------ amount -----------*/}
|
||||||
@@ -294,12 +221,3 @@ function OwnerContributionFormFields({
|
|||||||
</React.Fragment>
|
</React.Fragment>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export default compose(
|
|
||||||
withDialogActions,
|
|
||||||
withSettings(({ cashflowSetting }) => ({
|
|
||||||
transactionAutoIncrement: cashflowSetting?.autoIncrement,
|
|
||||||
transactionNextNumber: cashflowSetting?.nextNumber,
|
|
||||||
transactionNumberPrefix: cashflowSetting?.numberPrefix,
|
|
||||||
})),
|
|
||||||
)(OwnerContributionFormFields);
|
|
||||||
@@ -17,11 +17,9 @@ import {
|
|||||||
InputPrependText,
|
InputPrependText,
|
||||||
MoneyInputGroup,
|
MoneyInputGroup,
|
||||||
FieldRequiredHint,
|
FieldRequiredHint,
|
||||||
Icon,
|
|
||||||
Col,
|
Col,
|
||||||
Row,
|
Row,
|
||||||
If,
|
If,
|
||||||
InputPrependButton,
|
|
||||||
ExchangeRateMutedField,
|
ExchangeRateMutedField,
|
||||||
FeatureCan,
|
FeatureCan,
|
||||||
BranchSelect,
|
BranchSelect,
|
||||||
@@ -35,30 +33,20 @@ import {
|
|||||||
momentFormatter,
|
momentFormatter,
|
||||||
tansformDateValue,
|
tansformDateValue,
|
||||||
handleDateChange,
|
handleDateChange,
|
||||||
compose,
|
|
||||||
} from '@/utils';
|
} from '@/utils';
|
||||||
import { useMoneyInDailogContext } from '../MoneyInDialogProvider';
|
import { useMoneyInDailogContext } from '../MoneyInDialogProvider';
|
||||||
import {
|
import {
|
||||||
useObserveTransactionNoSettings,
|
|
||||||
useSetPrimaryBranchToForm,
|
useSetPrimaryBranchToForm,
|
||||||
useForeignAccount,
|
useForeignAccount,
|
||||||
BranchRowDivider,
|
BranchRowDivider,
|
||||||
} from '../../MoneyInDialog/utils';
|
} from '../../MoneyInDialog/utils';
|
||||||
import withSettings from '@/containers/Settings/withSettings';
|
|
||||||
import withDialogActions from '@/containers/Dialog/withDialogActions';
|
import { MoneyInOutTransactionNoField } from '../../_components';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Transfer from account form fields.
|
* Transfer from account form fields.
|
||||||
*/
|
*/
|
||||||
function TransferFromAccountFormFields({
|
export default function TransferFromAccountFormFields() {
|
||||||
// #withDialogActions
|
|
||||||
openDialog,
|
|
||||||
|
|
||||||
// #withSettings
|
|
||||||
transactionAutoIncrement,
|
|
||||||
transactionNumberPrefix,
|
|
||||||
transactionNextNumber,
|
|
||||||
}) {
|
|
||||||
// Money in dialog context.
|
// Money in dialog context.
|
||||||
const { accounts, account, branches } = useMoneyInDailogContext();
|
const { accounts, account, branches } = useMoneyInDailogContext();
|
||||||
|
|
||||||
@@ -67,33 +55,9 @@ function TransferFromAccountFormFields({
|
|||||||
|
|
||||||
const { values } = useFormikContext();
|
const { values } = useFormikContext();
|
||||||
|
|
||||||
// Handle tranaction number changing.
|
|
||||||
const handleTransactionNumberChange = () => {
|
|
||||||
openDialog('transaction-number-form');
|
|
||||||
};
|
|
||||||
|
|
||||||
// Handle transaction no. field blur.
|
|
||||||
const handleTransactionNoBlur = (form, field) => (event) => {
|
|
||||||
const newValue = event.target.value;
|
|
||||||
|
|
||||||
if (field.value !== newValue && transactionAutoIncrement) {
|
|
||||||
openDialog('transaction-number-form', {
|
|
||||||
initialFormValues: {
|
|
||||||
manualTransactionNo: newValue,
|
|
||||||
incrementMode: 'manual-transaction',
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Sets the primary branch to form.
|
// Sets the primary branch to form.
|
||||||
useSetPrimaryBranchToForm();
|
useSetPrimaryBranchToForm();
|
||||||
|
|
||||||
// Syncs transaction number settings with form.
|
|
||||||
useObserveTransactionNoSettings(
|
|
||||||
transactionNumberPrefix,
|
|
||||||
transactionNextNumber,
|
|
||||||
);
|
|
||||||
return (
|
return (
|
||||||
<React.Fragment>
|
<React.Fragment>
|
||||||
<FeatureCan feature={Features.Branches}>
|
<FeatureCan feature={Features.Branches}>
|
||||||
@@ -145,42 +109,7 @@ function TransferFromAccountFormFields({
|
|||||||
</Col>
|
</Col>
|
||||||
<Col xs={5}>
|
<Col xs={5}>
|
||||||
{/*------------ Transaction number -----------*/}
|
{/*------------ Transaction number -----------*/}
|
||||||
<Field name={'transaction_number'}>
|
<MoneyInOutTransactionNoField />
|
||||||
{({ form, field, meta: { error, touched } }) => (
|
|
||||||
<FormGroup
|
|
||||||
label={<T id={'transaction_number'} />}
|
|
||||||
intent={inputIntent({ error, touched })}
|
|
||||||
helperText={<ErrorMessage name="transaction_number" />}
|
|
||||||
className={'form-group--transaction_number'}
|
|
||||||
>
|
|
||||||
<ControlGroup fill={true}>
|
|
||||||
<InputGroup
|
|
||||||
minimal={true}
|
|
||||||
value={field.value}
|
|
||||||
asyncControl={true}
|
|
||||||
onBlur={handleTransactionNoBlur(form, field)}
|
|
||||||
/>
|
|
||||||
<InputPrependButton
|
|
||||||
buttonProps={{
|
|
||||||
onClick: handleTransactionNumberChange,
|
|
||||||
icon: <Icon icon={'settings-18'} />,
|
|
||||||
}}
|
|
||||||
tooltip={true}
|
|
||||||
tooltipProps={{
|
|
||||||
content: (
|
|
||||||
<T
|
|
||||||
id={
|
|
||||||
'cash_flow.setting_your_auto_generated_transaction_number'
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
),
|
|
||||||
position: Position.BOTTOM_LEFT,
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</ControlGroup>
|
|
||||||
</FormGroup>
|
|
||||||
)}
|
|
||||||
</Field>
|
|
||||||
</Col>
|
</Col>
|
||||||
</Row>
|
</Row>
|
||||||
{/*------------ amount -----------*/}
|
{/*------------ amount -----------*/}
|
||||||
@@ -296,12 +225,3 @@ function TransferFromAccountFormFields({
|
|||||||
</React.Fragment>
|
</React.Fragment>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export default compose(
|
|
||||||
withDialogActions,
|
|
||||||
withSettings(({ cashflowSetting }) => ({
|
|
||||||
transactionAutoIncrement: cashflowSetting?.autoIncrement,
|
|
||||||
transactionNextNumber: cashflowSetting?.nextNumber,
|
|
||||||
transactionNumberPrefix: cashflowSetting?.numberPrefix,
|
|
||||||
})),
|
|
||||||
)(TransferFromAccountFormFields);
|
|
||||||
@@ -20,7 +20,6 @@ function MoneyOutContentFields({ accountType }) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
return <React.Fragment>{handleTransactionType()}</React.Fragment>;
|
return <React.Fragment>{handleTransactionType()}</React.Fragment>;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -32,7 +32,6 @@ function MoneyOutFloatingActions({
|
|||||||
// Handle submit button click.
|
// Handle submit button click.
|
||||||
const handleSubmittBtnClick = (event) => {
|
const handleSubmittBtnClick = (event) => {
|
||||||
setSubmitPayload({ publish: true });
|
setSubmitPayload({ publish: true });
|
||||||
submitForm();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Handle close button click.
|
// Handle close button click.
|
||||||
@@ -3,8 +3,10 @@ import React from 'react';
|
|||||||
import { Form } from 'formik';
|
import { Form } from 'formik';
|
||||||
|
|
||||||
import MoneyOutFormFields from './MoneyOutFormFields';
|
import MoneyOutFormFields from './MoneyOutFormFields';
|
||||||
import MoneyOutFormDialog from './MoneyOutFormDialog'
|
import MoneyOutFormDialog from './MoneyOutFormDialog';
|
||||||
import MoneyOutFloatingActions from './MoneyOutFloatingActions';
|
import MoneyOutFloatingActions from './MoneyOutFloatingActions';
|
||||||
|
import { MoneyInOutSyncIncrementSettingsToForm } from '../_components';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Money out form content.
|
* Money out form content.
|
||||||
*/
|
*/
|
||||||
@@ -12,8 +14,9 @@ export default function MoneyOutFormContent() {
|
|||||||
return (
|
return (
|
||||||
<Form>
|
<Form>
|
||||||
<MoneyOutFormFields />
|
<MoneyOutFormFields />
|
||||||
<MoneyOutFormDialog/>
|
<MoneyOutFormDialog />
|
||||||
<MoneyOutFloatingActions />
|
<MoneyOutFloatingActions />
|
||||||
|
<MoneyInOutSyncIncrementSettingsToForm />
|
||||||
</Form>
|
</Form>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -16,11 +16,9 @@ import {
|
|||||||
InputPrependText,
|
InputPrependText,
|
||||||
MoneyInputGroup,
|
MoneyInputGroup,
|
||||||
FieldRequiredHint,
|
FieldRequiredHint,
|
||||||
Icon,
|
|
||||||
Col,
|
Col,
|
||||||
Row,
|
Row,
|
||||||
If,
|
If,
|
||||||
InputPrependButton,
|
|
||||||
FeatureCan,
|
FeatureCan,
|
||||||
BranchSelect,
|
BranchSelect,
|
||||||
BranchSelectButton,
|
BranchSelectButton,
|
||||||
@@ -35,31 +33,21 @@ import {
|
|||||||
momentFormatter,
|
momentFormatter,
|
||||||
tansformDateValue,
|
tansformDateValue,
|
||||||
handleDateChange,
|
handleDateChange,
|
||||||
compose,
|
|
||||||
} from '@/utils';
|
} from '@/utils';
|
||||||
import { CLASSES } from '@/constants/classes';
|
import { CLASSES } from '@/constants/classes';
|
||||||
import { useMoneyOutDialogContext } from '../MoneyOutDialogProvider';
|
import { useMoneyOutDialogContext } from '../MoneyOutDialogProvider';
|
||||||
import {
|
import {
|
||||||
useObserveTransactionNoSettings,
|
|
||||||
useSetPrimaryBranchToForm,
|
useSetPrimaryBranchToForm,
|
||||||
useForeignAccount,
|
useForeignAccount,
|
||||||
BranchRowDivider,
|
BranchRowDivider,
|
||||||
} from '../utils';
|
} from '../utils';
|
||||||
import withSettings from '@/containers/Settings/withSettings';
|
|
||||||
import withDialogActions from '@/containers/Dialog/withDialogActions';
|
import { MoneyInOutTransactionNoField } from '../../_components';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Other expense form fields.
|
* Other expense form fields.
|
||||||
*/
|
*/
|
||||||
function OtherExpnseFormFields({
|
export default function OtherExpnseFormFields() {
|
||||||
// #withDialogActions
|
|
||||||
openDialog,
|
|
||||||
|
|
||||||
// #withSettings
|
|
||||||
transactionAutoIncrement,
|
|
||||||
transactionNumberPrefix,
|
|
||||||
transactionNextNumber,
|
|
||||||
}) {
|
|
||||||
// Money in dialog context.
|
// Money in dialog context.
|
||||||
const { accounts, account, branches } = useMoneyOutDialogContext();
|
const { accounts, account, branches } = useMoneyOutDialogContext();
|
||||||
|
|
||||||
@@ -68,31 +56,6 @@ function OtherExpnseFormFields({
|
|||||||
|
|
||||||
const amountFieldRef = useAutofocus();
|
const amountFieldRef = useAutofocus();
|
||||||
|
|
||||||
// Handle tranaction number changing.
|
|
||||||
const handleTransactionNumberChange = () => {
|
|
||||||
openDialog('transaction-number-form');
|
|
||||||
};
|
|
||||||
|
|
||||||
// Handle transaction no. field blur.
|
|
||||||
const handleTransactionNoBlur = (form, field) => (event) => {
|
|
||||||
const newValue = event.target.value;
|
|
||||||
|
|
||||||
if (field.value !== newValue && transactionAutoIncrement) {
|
|
||||||
openDialog('transaction-number-form', {
|
|
||||||
initialFormValues: {
|
|
||||||
manualTransactionNo: newValue,
|
|
||||||
incrementMode: 'manual-transaction',
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Syncs transaction number settings with form.
|
|
||||||
useObserveTransactionNoSettings(
|
|
||||||
transactionNumberPrefix,
|
|
||||||
transactionNextNumber,
|
|
||||||
);
|
|
||||||
|
|
||||||
// Sets the primary branch to form.
|
// Sets the primary branch to form.
|
||||||
useSetPrimaryBranchToForm();
|
useSetPrimaryBranchToForm();
|
||||||
|
|
||||||
@@ -147,42 +110,7 @@ function OtherExpnseFormFields({
|
|||||||
</Col>
|
</Col>
|
||||||
<Col xs={5}>
|
<Col xs={5}>
|
||||||
{/*------------ Transaction number -----------*/}
|
{/*------------ Transaction number -----------*/}
|
||||||
<Field name={'transaction_number'}>
|
<MoneyInOutTransactionNoField />
|
||||||
{({ form, field, meta: { error, touched } }) => (
|
|
||||||
<FormGroup
|
|
||||||
label={<T id={'transaction_number'} />}
|
|
||||||
intent={inputIntent({ error, touched })}
|
|
||||||
helperText={<ErrorMessage name="transaction_number" />}
|
|
||||||
className={'form-group--transaction_number'}
|
|
||||||
>
|
|
||||||
<ControlGroup fill={true}>
|
|
||||||
<InputGroup
|
|
||||||
minimal={true}
|
|
||||||
value={field.value}
|
|
||||||
asyncControl={true}
|
|
||||||
onBlur={handleTransactionNoBlur(form, field)}
|
|
||||||
/>
|
|
||||||
<InputPrependButton
|
|
||||||
buttonProps={{
|
|
||||||
onClick: handleTransactionNumberChange,
|
|
||||||
icon: <Icon icon={'settings-18'} />,
|
|
||||||
}}
|
|
||||||
tooltip={true}
|
|
||||||
tooltipProps={{
|
|
||||||
content: (
|
|
||||||
<T
|
|
||||||
id={
|
|
||||||
'cash_flow.setting_your_auto_generated_transaction_number'
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
),
|
|
||||||
position: Position.BOTTOM_LEFT,
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</ControlGroup>
|
|
||||||
</FormGroup>
|
|
||||||
)}
|
|
||||||
</Field>
|
|
||||||
</Col>
|
</Col>
|
||||||
</Row>
|
</Row>
|
||||||
{/*------------ amount -----------*/}
|
{/*------------ amount -----------*/}
|
||||||
@@ -296,12 +224,3 @@ function OtherExpnseFormFields({
|
|||||||
</React.Fragment>
|
</React.Fragment>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export default compose(
|
|
||||||
withDialogActions,
|
|
||||||
withSettings(({ cashflowSetting }) => ({
|
|
||||||
transactionAutoIncrement: cashflowSetting?.autoIncrement,
|
|
||||||
transactionNextNumber: cashflowSetting?.nextNumber,
|
|
||||||
transactionNumberPrefix: cashflowSetting?.numberPrefix,
|
|
||||||
})),
|
|
||||||
)(OtherExpnseFormFields);
|
|
||||||
@@ -17,8 +17,6 @@ import {
|
|||||||
InputPrependText,
|
InputPrependText,
|
||||||
MoneyInputGroup,
|
MoneyInputGroup,
|
||||||
FieldRequiredHint,
|
FieldRequiredHint,
|
||||||
InputPrependButton,
|
|
||||||
Icon,
|
|
||||||
If,
|
If,
|
||||||
Col,
|
Col,
|
||||||
Row,
|
Row,
|
||||||
@@ -34,30 +32,19 @@ import {
|
|||||||
momentFormatter,
|
momentFormatter,
|
||||||
tansformDateValue,
|
tansformDateValue,
|
||||||
handleDateChange,
|
handleDateChange,
|
||||||
compose,
|
|
||||||
} from '@/utils';
|
} from '@/utils';
|
||||||
import { useMoneyOutDialogContext } from '../MoneyOutDialogProvider';
|
import { useMoneyOutDialogContext } from '../MoneyOutDialogProvider';
|
||||||
import {
|
import {
|
||||||
useObserveTransactionNoSettings,
|
|
||||||
useSetPrimaryBranchToForm,
|
useSetPrimaryBranchToForm,
|
||||||
useForeignAccount,
|
useForeignAccount,
|
||||||
BranchRowDivider,
|
BranchRowDivider,
|
||||||
} from '../../MoneyOutDialog/utils';
|
} from '../../MoneyOutDialog/utils';
|
||||||
import withSettings from '@/containers/Settings/withSettings';
|
import { MoneyInOutTransactionNoField } from '../../_components';
|
||||||
import withDialogActions from '@/containers/Dialog/withDialogActions';
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Owner drawings form fields.
|
* Owner drawings form fields.
|
||||||
*/
|
*/
|
||||||
function OwnerDrawingsFormFields({
|
export default function OwnerDrawingsFormFields() {
|
||||||
// #withDialogActions
|
|
||||||
openDialog,
|
|
||||||
|
|
||||||
// #withSettings
|
|
||||||
transactionAutoIncrement,
|
|
||||||
transactionNumberPrefix,
|
|
||||||
transactionNextNumber,
|
|
||||||
}) {
|
|
||||||
// Money out dialog context.
|
// Money out dialog context.
|
||||||
const { accounts, account, branches } = useMoneyOutDialogContext();
|
const { accounts, account, branches } = useMoneyOutDialogContext();
|
||||||
const { values } = useFormikContext();
|
const { values } = useFormikContext();
|
||||||
@@ -65,31 +52,6 @@ function OwnerDrawingsFormFields({
|
|||||||
|
|
||||||
const amountFieldRef = useAutofocus();
|
const amountFieldRef = useAutofocus();
|
||||||
|
|
||||||
// Handle tranaction number changing.
|
|
||||||
const handleTransactionNumberChange = () => {
|
|
||||||
openDialog('transaction-number-form');
|
|
||||||
};
|
|
||||||
|
|
||||||
// Handle transaction no. field blur.
|
|
||||||
const handleTransactionNoBlur = (form, field) => (event) => {
|
|
||||||
const newValue = event.target.value;
|
|
||||||
|
|
||||||
if (field.value !== newValue && transactionAutoIncrement) {
|
|
||||||
openDialog('transaction-number-form', {
|
|
||||||
initialFormValues: {
|
|
||||||
manualTransactionNo: newValue,
|
|
||||||
incrementMode: 'manual-transaction',
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Syncs transaction number settings with form.
|
|
||||||
useObserveTransactionNoSettings(
|
|
||||||
transactionNumberPrefix,
|
|
||||||
transactionNextNumber,
|
|
||||||
);
|
|
||||||
|
|
||||||
// Sets the primary branch to form.
|
// Sets the primary branch to form.
|
||||||
useSetPrimaryBranchToForm();
|
useSetPrimaryBranchToForm();
|
||||||
|
|
||||||
@@ -144,42 +106,7 @@ function OwnerDrawingsFormFields({
|
|||||||
</Col>
|
</Col>
|
||||||
<Col xs={5}>
|
<Col xs={5}>
|
||||||
{/*------------ Transaction number -----------*/}
|
{/*------------ Transaction number -----------*/}
|
||||||
<Field name={'transaction_number'}>
|
<MoneyInOutTransactionNoField />
|
||||||
{({ form, field, meta: { error, touched } }) => (
|
|
||||||
<FormGroup
|
|
||||||
label={<T id={'transaction_number'} />}
|
|
||||||
intent={inputIntent({ error, touched })}
|
|
||||||
helperText={<ErrorMessage name="transaction_number" />}
|
|
||||||
className={'form-group--transaction_number'}
|
|
||||||
>
|
|
||||||
<ControlGroup fill={true}>
|
|
||||||
<InputGroup
|
|
||||||
minimal={true}
|
|
||||||
value={field.value}
|
|
||||||
asyncControl={true}
|
|
||||||
onBlur={handleTransactionNoBlur(form, field)}
|
|
||||||
/>
|
|
||||||
<InputPrependButton
|
|
||||||
buttonProps={{
|
|
||||||
onClick: handleTransactionNumberChange,
|
|
||||||
icon: <Icon icon={'settings-18'} />,
|
|
||||||
}}
|
|
||||||
tooltip={true}
|
|
||||||
tooltipProps={{
|
|
||||||
content: (
|
|
||||||
<T
|
|
||||||
id={
|
|
||||||
'cash_flow.setting_your_auto_generated_transaction_number'
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
),
|
|
||||||
position: Position.BOTTOM_LEFT,
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</ControlGroup>
|
|
||||||
</FormGroup>
|
|
||||||
)}
|
|
||||||
</Field>
|
|
||||||
</Col>
|
</Col>
|
||||||
</Row>
|
</Row>
|
||||||
{/*------------ amount -----------*/}
|
{/*------------ amount -----------*/}
|
||||||
@@ -291,12 +218,3 @@ function OwnerDrawingsFormFields({
|
|||||||
</React.Fragment>
|
</React.Fragment>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export default compose(
|
|
||||||
withDialogActions,
|
|
||||||
withSettings(({ cashflowSetting }) => ({
|
|
||||||
transactionAutoIncrement: cashflowSetting?.autoIncrement,
|
|
||||||
transactionNextNumber: cashflowSetting?.nextNumber,
|
|
||||||
transactionNumberPrefix: cashflowSetting?.numberPrefix,
|
|
||||||
})),
|
|
||||||
)(OwnerDrawingsFormFields);
|
|
||||||
@@ -48,19 +48,12 @@ import {
|
|||||||
} from '../utils';
|
} from '../utils';
|
||||||
import withSettings from '@/containers/Settings/withSettings';
|
import withSettings from '@/containers/Settings/withSettings';
|
||||||
import withDialogActions from '@/containers/Dialog/withDialogActions';
|
import withDialogActions from '@/containers/Dialog/withDialogActions';
|
||||||
|
import { MoneyInOutTransactionNoField } from '../../_components';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Transfer to account form fields.
|
* Transfer to account form fields.
|
||||||
*/
|
*/
|
||||||
function TransferToAccountFormFields({
|
export default function TransferToAccountFormFields() {
|
||||||
// #withDialogActions
|
|
||||||
openDialog,
|
|
||||||
|
|
||||||
// #withSettings
|
|
||||||
transactionAutoIncrement,
|
|
||||||
transactionNumberPrefix,
|
|
||||||
transactionNextNumber,
|
|
||||||
}) {
|
|
||||||
// Money in dialog context.
|
// Money in dialog context.
|
||||||
const { accounts, account, branches } = useMoneyOutDialogContext();
|
const { accounts, account, branches } = useMoneyOutDialogContext();
|
||||||
const { values } = useFormikContext();
|
const { values } = useFormikContext();
|
||||||
@@ -68,31 +61,6 @@ function TransferToAccountFormFields({
|
|||||||
|
|
||||||
const accountRef = useAutofocus();
|
const accountRef = useAutofocus();
|
||||||
|
|
||||||
// Handle tranaction number changing.
|
|
||||||
const handleTransactionNumberChange = () => {
|
|
||||||
openDialog('transaction-number-form');
|
|
||||||
};
|
|
||||||
|
|
||||||
// Handle transaction no. field blur.
|
|
||||||
const handleTransactionNoBlur = (form, field) => (event) => {
|
|
||||||
const newValue = event.target.value;
|
|
||||||
|
|
||||||
if (field.value !== newValue && transactionAutoIncrement) {
|
|
||||||
openDialog('transaction-number-form', {
|
|
||||||
initialFormValues: {
|
|
||||||
manualTransactionNo: newValue,
|
|
||||||
incrementMode: 'manual-transaction',
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Syncs transaction number settings with form.
|
|
||||||
useObserveTransactionNoSettings(
|
|
||||||
transactionNumberPrefix,
|
|
||||||
transactionNextNumber,
|
|
||||||
);
|
|
||||||
|
|
||||||
// Sets the primary branch to form.
|
// Sets the primary branch to form.
|
||||||
useSetPrimaryBranchToForm();
|
useSetPrimaryBranchToForm();
|
||||||
|
|
||||||
@@ -147,42 +115,7 @@ function TransferToAccountFormFields({
|
|||||||
</Col>
|
</Col>
|
||||||
<Col xs={5}>
|
<Col xs={5}>
|
||||||
{/*------------ Transaction number -----------*/}
|
{/*------------ Transaction number -----------*/}
|
||||||
<Field name={'transaction_number'}>
|
<MoneyInOutTransactionNoField />
|
||||||
{({ form, field, meta: { error, touched } }) => (
|
|
||||||
<FormGroup
|
|
||||||
label={<T id={'transaction_number'} />}
|
|
||||||
intent={inputIntent({ error, touched })}
|
|
||||||
helperText={<ErrorMessage name="transaction_number" />}
|
|
||||||
className={'form-group--transaction_number'}
|
|
||||||
>
|
|
||||||
<ControlGroup fill={true}>
|
|
||||||
<InputGroup
|
|
||||||
minimal={true}
|
|
||||||
value={field.value}
|
|
||||||
asyncControl={true}
|
|
||||||
onBlur={handleTransactionNoBlur(form, field)}
|
|
||||||
/>
|
|
||||||
<InputPrependButton
|
|
||||||
buttonProps={{
|
|
||||||
onClick: handleTransactionNumberChange,
|
|
||||||
icon: <Icon icon={'settings-18'} />,
|
|
||||||
}}
|
|
||||||
tooltip={true}
|
|
||||||
tooltipProps={{
|
|
||||||
content: (
|
|
||||||
<T
|
|
||||||
id={
|
|
||||||
'cash_flow.setting_your_auto_generated_transaction_number'
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
),
|
|
||||||
position: Position.BOTTOM_LEFT,
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</ControlGroup>
|
|
||||||
</FormGroup>
|
|
||||||
)}
|
|
||||||
</Field>
|
|
||||||
</Col>
|
</Col>
|
||||||
</Row>
|
</Row>
|
||||||
{/*------------ amount -----------*/}
|
{/*------------ amount -----------*/}
|
||||||
@@ -298,11 +231,3 @@ function TransferToAccountFormFields({
|
|||||||
</React.Fragment>
|
</React.Fragment>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
export default compose(
|
|
||||||
withDialogActions,
|
|
||||||
withSettings(({ cashflowSetting }) => ({
|
|
||||||
transactionAutoIncrement: cashflowSetting?.autoIncrement,
|
|
||||||
transactionNextNumber: cashflowSetting?.nextNumber,
|
|
||||||
transactionNumberPrefix: cashflowSetting?.numberPrefix,
|
|
||||||
})),
|
|
||||||
)(TransferToAccountFormFields);
|
|
||||||
127
packages/webapp/src/containers/CashFlow/_components.tsx
Normal file
127
packages/webapp/src/containers/CashFlow/_components.tsx
Normal file
@@ -0,0 +1,127 @@
|
|||||||
|
// @ts-nocheck
|
||||||
|
import React from 'react';
|
||||||
|
import { useFormikContext } from 'formik';
|
||||||
|
import { InputGroup, Position, ControlGroup } from '@blueprintjs/core';
|
||||||
|
import * as R from 'ramda';
|
||||||
|
|
||||||
|
import {
|
||||||
|
FFormGroup,
|
||||||
|
Icon,
|
||||||
|
InputPrependButton,
|
||||||
|
FormattedMessage as T,
|
||||||
|
} from '@/components';
|
||||||
|
import { useUpdateEffect } from '@/hooks';
|
||||||
|
|
||||||
|
import withSettings from '@/containers/Settings/withSettings';
|
||||||
|
import withDialogActions from '@/containers/Dialog/withDialogActions';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Syncs cashflow auto-increment settings to the form once update.
|
||||||
|
*/
|
||||||
|
export const MoneyInOutSyncIncrementSettingsToForm = R.compose(
|
||||||
|
withDialogActions,
|
||||||
|
withSettings(({ cashflowSetting }) => ({
|
||||||
|
transactionAutoIncrement: cashflowSetting?.autoIncrement,
|
||||||
|
transactionNextNumber: cashflowSetting?.nextNumber,
|
||||||
|
transactionNumberPrefix: cashflowSetting?.numberPrefix,
|
||||||
|
})),
|
||||||
|
)(
|
||||||
|
({
|
||||||
|
// #withSettings
|
||||||
|
transactionAutoIncrement,
|
||||||
|
transactionNextNumber,
|
||||||
|
transactionNumberPrefix,
|
||||||
|
}) => {
|
||||||
|
const { setFieldValue } = useFormikContext();
|
||||||
|
|
||||||
|
useUpdateEffect(() => {
|
||||||
|
// Do not update if the invoice auto-increment is disabled.
|
||||||
|
if (!transactionAutoIncrement) return null;
|
||||||
|
|
||||||
|
const transactionNumber = transactionNumber(
|
||||||
|
transactionNumberPrefix,
|
||||||
|
transactionNextNumber,
|
||||||
|
);
|
||||||
|
setFieldValue('transaction_number', transactionNumber);
|
||||||
|
}, [setFieldValue, transactionNumberPrefix, transactionNextNumber]);
|
||||||
|
|
||||||
|
return null;
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Money In/Out transaction number field.
|
||||||
|
*/
|
||||||
|
export const MoneyInOutTransactionNoField = R.compose(
|
||||||
|
withDialogActions,
|
||||||
|
withSettings(({ cashflowSetting }) => ({
|
||||||
|
transactionAutoIncrement: cashflowSetting?.autoIncrement,
|
||||||
|
transactionNextNumber: cashflowSetting?.nextNumber,
|
||||||
|
transactionNumberPrefix: cashflowSetting?.numberPrefix,
|
||||||
|
})),
|
||||||
|
)(
|
||||||
|
({
|
||||||
|
// #withDialogActions
|
||||||
|
openDialog,
|
||||||
|
|
||||||
|
// #withSettings
|
||||||
|
transactionAutoIncrement,
|
||||||
|
}) => {
|
||||||
|
const { values, setFieldValue } = useFormikContext();
|
||||||
|
|
||||||
|
// Handle tranaction number changing.
|
||||||
|
const handleTransactionNumberChange = () => {
|
||||||
|
openDialog('transaction-number-form');
|
||||||
|
};
|
||||||
|
// Handle transaction no. field blur.
|
||||||
|
const handleTransactionNoBlur = (event) => {
|
||||||
|
const newValue = event.target.value;
|
||||||
|
|
||||||
|
if (values.transaction_number !== newValue && transactionAutoIncrement) {
|
||||||
|
openDialog('transaction-number-form', {
|
||||||
|
initialFormValues: {
|
||||||
|
onceManualNumber: newValue,
|
||||||
|
incrementMode: 'manual-transaction',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (!transactionAutoIncrement) {
|
||||||
|
setFieldValue('transaction_number', values.transaction_number);
|
||||||
|
setFieldValue('transaction_number_manually', values.transaction_number);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<FFormGroup
|
||||||
|
name={'transaction_number'}
|
||||||
|
label={<T id={'transaction_number'} />}
|
||||||
|
>
|
||||||
|
<ControlGroup fill={true}>
|
||||||
|
<InputGroup
|
||||||
|
minimal={true}
|
||||||
|
value={values.transaction_number}
|
||||||
|
asyncControl={true}
|
||||||
|
onBlur={handleTransactionNoBlur}
|
||||||
|
/>
|
||||||
|
<InputPrependButton
|
||||||
|
buttonProps={{
|
||||||
|
onClick: handleTransactionNumberChange,
|
||||||
|
icon: <Icon icon={'settings-18'} />,
|
||||||
|
}}
|
||||||
|
tooltip={true}
|
||||||
|
tooltipProps={{
|
||||||
|
content: (
|
||||||
|
<T
|
||||||
|
id={
|
||||||
|
'cash_flow.setting_your_auto_generated_transaction_number'
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
),
|
||||||
|
position: Position.BOTTOM_LEFT,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</ControlGroup>
|
||||||
|
</FFormGroup>
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
@@ -1,15 +1,12 @@
|
|||||||
// @ts-nocheck
|
// @ts-nocheck
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import moment from 'moment';
|
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import { FormGroup, Position, Classes, ControlGroup } from '@blueprintjs/core';
|
import { FormGroup, Position, Classes, ControlGroup } from '@blueprintjs/core';
|
||||||
import { DateInput } from '@blueprintjs/datetime';
|
import { FastField, ErrorMessage, useFormikContext } from 'formik';
|
||||||
import { FastField, ErrorMessage } from 'formik';
|
|
||||||
import { Features } from '@/constants';
|
import { Features } from '@/constants';
|
||||||
import {
|
import {
|
||||||
FFormGroup,
|
FFormGroup,
|
||||||
FormattedMessage as T,
|
FormattedMessage as T,
|
||||||
MoneyInputGroup,
|
|
||||||
InputPrependText,
|
InputPrependText,
|
||||||
CurrencySelectList,
|
CurrencySelectList,
|
||||||
BranchSelect,
|
BranchSelect,
|
||||||
@@ -17,10 +14,17 @@ import {
|
|||||||
FeatureCan,
|
FeatureCan,
|
||||||
Row,
|
Row,
|
||||||
Col,
|
Col,
|
||||||
|
FMoneyInputGroup,
|
||||||
|
ExchangeRateInputGroup,
|
||||||
|
FDateInput,
|
||||||
} from '@/components';
|
} from '@/components';
|
||||||
import { useCustomerFormContext } from './CustomerFormProvider';
|
import { useCustomerFormContext } from './CustomerFormProvider';
|
||||||
import { useSetPrimaryBranchToForm } from './utils';
|
import {
|
||||||
import { momentFormatter, tansformDateValue, inputIntent } from '@/utils';
|
openingBalanceFieldShouldUpdate,
|
||||||
|
useIsCustomerForeignCurrency,
|
||||||
|
useSetPrimaryBranchToForm,
|
||||||
|
} from './utils';
|
||||||
|
import { useCurrentOrganization } from '@/hooks/state';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Customer financial panel.
|
* Customer financial panel.
|
||||||
@@ -35,76 +39,6 @@ export default function CustomerFinancialPanel() {
|
|||||||
<div className={'tab-panel--financial'}>
|
<div className={'tab-panel--financial'}>
|
||||||
<Row>
|
<Row>
|
||||||
<Col xs={6}>
|
<Col xs={6}>
|
||||||
{/*------------ Opening balance at -----------*/}
|
|
||||||
<FastField name={'opening_balance_at'}>
|
|
||||||
{({ form, field: { value }, meta: { error, touched } }) => (
|
|
||||||
<FormGroup
|
|
||||||
label={<T id={'opening_balance_at'} />}
|
|
||||||
className={classNames('form-group--select-list', Classes.FILL)}
|
|
||||||
intent={inputIntent({ error, touched })}
|
|
||||||
inline={true}
|
|
||||||
helperText={<ErrorMessage name="opening_balance_at" />}
|
|
||||||
>
|
|
||||||
<DateInput
|
|
||||||
{...momentFormatter('YYYY/MM/DD')}
|
|
||||||
onChange={(date) => {
|
|
||||||
form.setFieldValue(
|
|
||||||
'opening_balance_at',
|
|
||||||
moment(date).format('YYYY-MM-DD'),
|
|
||||||
);
|
|
||||||
}}
|
|
||||||
value={tansformDateValue(value)}
|
|
||||||
popoverProps={{ position: Position.BOTTOM, minimal: true }}
|
|
||||||
disabled={customerId}
|
|
||||||
/>
|
|
||||||
</FormGroup>
|
|
||||||
)}
|
|
||||||
</FastField>
|
|
||||||
|
|
||||||
{/*------------ Opening balance -----------*/}
|
|
||||||
<FastField name={'opening_balance'}>
|
|
||||||
{({ form, field, field: { value }, meta: { error, touched } }) => (
|
|
||||||
<FormGroup
|
|
||||||
label={<T id={'opening_balance'} />}
|
|
||||||
className={classNames(
|
|
||||||
'form-group--opening-balance',
|
|
||||||
Classes.FILL,
|
|
||||||
)}
|
|
||||||
intent={inputIntent({ error, touched })}
|
|
||||||
inline={true}
|
|
||||||
>
|
|
||||||
<ControlGroup>
|
|
||||||
<InputPrependText text={form.values.currency_code} />
|
|
||||||
<MoneyInputGroup
|
|
||||||
value={value}
|
|
||||||
inputGroupProps={{ fill: true }}
|
|
||||||
disabled={customerId}
|
|
||||||
onChange={(balance) => {
|
|
||||||
form.setFieldValue('opening_balance', balance);
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</ControlGroup>
|
|
||||||
</FormGroup>
|
|
||||||
)}
|
|
||||||
</FastField>
|
|
||||||
|
|
||||||
{/*------------ Opening branch -----------*/}
|
|
||||||
<FeatureCan feature={Features.Branches}>
|
|
||||||
<FFormGroup
|
|
||||||
label={<T id={'customer.label.opening_branch'} />}
|
|
||||||
name={'opening_balance_branch_id'}
|
|
||||||
inline={true}
|
|
||||||
className={classNames('form-group--select-list', Classes.FILL)}
|
|
||||||
>
|
|
||||||
<BranchSelect
|
|
||||||
name={'opening_balance_branch_id'}
|
|
||||||
branches={branches}
|
|
||||||
input={BranchSelectButton}
|
|
||||||
popoverProps={{ minimal: true }}
|
|
||||||
/>
|
|
||||||
</FFormGroup>
|
|
||||||
</FeatureCan>
|
|
||||||
|
|
||||||
{/*------------ Currency -----------*/}
|
{/*------------ Currency -----------*/}
|
||||||
<FastField name={'currency_code'}>
|
<FastField name={'currency_code'}>
|
||||||
{({ form, field: { value }, meta: { error, touched } }) => (
|
{({ form, field: { value }, meta: { error, touched } }) => (
|
||||||
@@ -123,12 +57,130 @@ export default function CustomerFinancialPanel() {
|
|||||||
onCurrencySelected={(currency) => {
|
onCurrencySelected={(currency) => {
|
||||||
form.setFieldValue('currency_code', currency.currency_code);
|
form.setFieldValue('currency_code', currency.currency_code);
|
||||||
}}
|
}}
|
||||||
|
disabled={customerId}
|
||||||
/>
|
/>
|
||||||
</FormGroup>
|
</FormGroup>
|
||||||
)}
|
)}
|
||||||
</FastField>
|
</FastField>
|
||||||
|
|
||||||
|
{/*------------ Opening balance -----------*/}
|
||||||
|
<CustomerOpeningBalanceField />
|
||||||
|
|
||||||
|
{/*------ Opening Balance Exchange Rate -----*/}
|
||||||
|
<CustomerOpeningBalanceExchangeRateField />
|
||||||
|
|
||||||
|
{/*------------ Opening balance at -----------*/}
|
||||||
|
<CustomerOpeningBalanceAtField />
|
||||||
|
|
||||||
|
{/*------------ Opening branch -----------*/}
|
||||||
|
<FeatureCan feature={Features.Branches}>
|
||||||
|
<FFormGroup
|
||||||
|
label={<T id={'customer.label.opening_branch'} />}
|
||||||
|
name={'opening_balance_branch_id'}
|
||||||
|
inline={true}
|
||||||
|
className={classNames('form-group--select-list', Classes.FILL)}
|
||||||
|
>
|
||||||
|
<BranchSelect
|
||||||
|
name={'opening_balance_branch_id'}
|
||||||
|
branches={branches}
|
||||||
|
input={BranchSelectButton}
|
||||||
|
popoverProps={{ minimal: true }}
|
||||||
|
/>
|
||||||
|
</FFormGroup>
|
||||||
|
</FeatureCan>
|
||||||
</Col>
|
</Col>
|
||||||
</Row>
|
</Row>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Customer opening balance at date field.
|
||||||
|
* @returns {JSX.Element}
|
||||||
|
*/
|
||||||
|
function CustomerOpeningBalanceAtField() {
|
||||||
|
const { customerId } = useCustomerFormContext();
|
||||||
|
|
||||||
|
// Cannot continue if the customer id is defined.
|
||||||
|
if (customerId) return null;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<FormGroup
|
||||||
|
name={'opening_balance_at'}
|
||||||
|
label={<T id={'opening_balance_at'} />}
|
||||||
|
inline={true}
|
||||||
|
helperText={<ErrorMessage name="opening_balance_at" />}
|
||||||
|
>
|
||||||
|
<FDateInput
|
||||||
|
name={'opening_balance_at'}
|
||||||
|
popoverProps={{ position: Position.BOTTOM, minimal: true }}
|
||||||
|
disabled={customerId}
|
||||||
|
formatDate={(date) => date.toLocaleDateString()}
|
||||||
|
parseDate={(str) => new Date(str)}
|
||||||
|
fill={true}
|
||||||
|
/>
|
||||||
|
</FormGroup>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Customer opening balance field.
|
||||||
|
* @returns {JSX.Element}
|
||||||
|
*/
|
||||||
|
function CustomerOpeningBalanceField() {
|
||||||
|
const { customerId } = useCustomerFormContext();
|
||||||
|
const { values } = useFormikContext();
|
||||||
|
|
||||||
|
// Cannot continue if the customer id is defined.
|
||||||
|
if (customerId) return null;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<FFormGroup
|
||||||
|
label={<T id={'opening_balance'} />}
|
||||||
|
name={'opening_balance'}
|
||||||
|
inline={true}
|
||||||
|
shouldUpdate={openingBalanceFieldShouldUpdate}
|
||||||
|
shouldUpdateDeps={{ currencyCode: values.currency_code }}
|
||||||
|
fastField={true}
|
||||||
|
>
|
||||||
|
<ControlGroup>
|
||||||
|
<InputPrependText text={values.currency_code} />
|
||||||
|
<FMoneyInputGroup
|
||||||
|
name={'opening_balance'}
|
||||||
|
inputGroupProps={{ fill: true }}
|
||||||
|
/>
|
||||||
|
</ControlGroup>
|
||||||
|
</FFormGroup>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Customer opening balance exchange rate field if the customer has foreign
|
||||||
|
* currency.
|
||||||
|
* @returns {JSX.Element}
|
||||||
|
*/
|
||||||
|
function CustomerOpeningBalanceExchangeRateField() {
|
||||||
|
const { values } = useFormikContext();
|
||||||
|
const { customerId } = useCustomerFormContext();
|
||||||
|
const currentOrganization = useCurrentOrganization();
|
||||||
|
|
||||||
|
const isForeignJouranl = useIsCustomerForeignCurrency();
|
||||||
|
|
||||||
|
// Can't continue if the customer is not foreign.
|
||||||
|
if (!isForeignJouranl || customerId) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
<FFormGroup
|
||||||
|
label={' '}
|
||||||
|
name={'opening_balance_exchange_rate'}
|
||||||
|
inline={true}
|
||||||
|
>
|
||||||
|
<ExchangeRateInputGroup
|
||||||
|
fromCurrency={values.currency_code}
|
||||||
|
toCurrency={currentOrganization.base_currency}
|
||||||
|
name={'opening_balance_exchange_rate'}
|
||||||
|
/>
|
||||||
|
</FFormGroup>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|||||||
@@ -32,11 +32,6 @@ export default function CustomersTabs() {
|
|||||||
title={intl.get('notes')}
|
title={intl.get('notes')}
|
||||||
panel={<CustomerNotePanel />}
|
panel={<CustomerNotePanel />}
|
||||||
/>
|
/>
|
||||||
<Tab
|
|
||||||
id={'attachement'}
|
|
||||||
title={intl.get('attachement')}
|
|
||||||
panel={<CustomerAttachmentTabs />}
|
|
||||||
/>
|
|
||||||
</Tabs>
|
</Tabs>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import { useFormikContext } from 'formik';
|
|||||||
import { first } from 'lodash';
|
import { first } from 'lodash';
|
||||||
|
|
||||||
import { useCustomerFormContext } from './CustomerFormProvider';
|
import { useCustomerFormContext } from './CustomerFormProvider';
|
||||||
|
import { useCurrentOrganization } from '@/hooks/state';
|
||||||
|
|
||||||
export const defaultInitialValues = {
|
export const defaultInitialValues = {
|
||||||
customer_type: 'business',
|
customer_type: 'business',
|
||||||
@@ -37,9 +38,11 @@ export const defaultInitialValues = {
|
|||||||
shipping_address_postcode: '',
|
shipping_address_postcode: '',
|
||||||
shipping_address_phone: '',
|
shipping_address_phone: '',
|
||||||
|
|
||||||
opening_balance: '',
|
|
||||||
currency_code: '',
|
currency_code: '',
|
||||||
|
|
||||||
|
opening_balance: '',
|
||||||
opening_balance_at: moment(new Date()).format('YYYY-MM-DD'),
|
opening_balance_at: moment(new Date()).format('YYYY-MM-DD'),
|
||||||
|
opening_balance_exchange_rate: '',
|
||||||
opening_balance_branch_id: '',
|
opening_balance_branch_id: '',
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -57,3 +60,25 @@ export const useSetPrimaryBranchToForm = () => {
|
|||||||
}
|
}
|
||||||
}, [isBranchesSuccess, setFieldValue, branches]);
|
}, [isBranchesSuccess, setFieldValue, branches]);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Detarmines whether the current customer has foreign currency.
|
||||||
|
* @returns {boolean}
|
||||||
|
*/
|
||||||
|
export const useIsCustomerForeignCurrency = () => {
|
||||||
|
const currentOrganization = useCurrentOrganization();
|
||||||
|
const { values } = useFormikContext();
|
||||||
|
|
||||||
|
return currentOrganization.base_currency !== values.currency_code;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Detarmines the exchange opening balance field when should update.
|
||||||
|
*/
|
||||||
|
export const openingBalanceFieldShouldUpdate = (newProps, oldProps) => {
|
||||||
|
return (
|
||||||
|
newProps.shouldUpdateDeps.currencyCode !==
|
||||||
|
oldProps.shouldUpdateDeps.currencyCode ||
|
||||||
|
defaultFastFieldShouldUpdate(newProps, oldProps)
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|||||||
@@ -38,7 +38,6 @@ export function ActionsMenu({
|
|||||||
/>
|
/>
|
||||||
<Can I={CustomerAction.Edit} a={AbilitySubject.Customer}>
|
<Can I={CustomerAction.Edit} a={AbilitySubject.Customer}>
|
||||||
<MenuDivider />
|
<MenuDivider />
|
||||||
|
|
||||||
<MenuItem
|
<MenuItem
|
||||||
icon={<Icon icon="pen-18" />}
|
icon={<Icon icon="pen-18" />}
|
||||||
text={intl.get('edit_customer')}
|
text={intl.get('edit_customer')}
|
||||||
@@ -47,7 +46,7 @@ export function ActionsMenu({
|
|||||||
</Can>
|
</Can>
|
||||||
<Can I={CustomerAction.Create} a={AbilitySubject.Customer}>
|
<Can I={CustomerAction.Create} a={AbilitySubject.Customer}>
|
||||||
<MenuItem
|
<MenuItem
|
||||||
icon={<Icon icon="duplicate-16" />}
|
icon={<Icon icon="content-copy" iconSize={16} />}
|
||||||
text={intl.get('duplicate')}
|
text={intl.get('duplicate')}
|
||||||
onClick={safeCallback(onDuplicate, original)}
|
onClick={safeCallback(onDuplicate, original)}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -34,10 +34,10 @@ export function Sidebar() {
|
|||||||
* @returns {React.JSX}
|
* @returns {React.JSX}
|
||||||
*/
|
*/
|
||||||
function SidebarFooterVersion() {
|
function SidebarFooterVersion() {
|
||||||
const { VERSION } = process.env;
|
const { MONOREPO_VERSION } = process.env;
|
||||||
|
|
||||||
if (!VERSION) {
|
if (!MONOREPO_VERSION) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return <div class="sidebar__version">v{VERSION}</div>;
|
return <div class="sidebar__version">v{MONOREPO_VERSION}</div>;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,8 +7,10 @@ export const mapStateToProps = (state, props) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const mapDispatchToProps = (dispatch) => ({
|
export const mapDispatchToProps = (dispatch) => ({
|
||||||
openDialog: (name, payload) => dispatch({ type: t.OPEN_DIALOG, name, payload }),
|
openDialog: (name, payload) =>
|
||||||
closeDialog: (name, payload) => dispatch({ type: t.CLOSE_DIALOG, name, payload }),
|
dispatch({ type: t.OPEN_DIALOG, name, payload }),
|
||||||
|
closeDialog: (name, payload) =>
|
||||||
|
dispatch({ type: t.CLOSE_DIALOG, name, payload }),
|
||||||
});
|
});
|
||||||
|
|
||||||
export default connect(null, mapDispatchToProps);
|
export default connect(null, mapDispatchToProps);
|
||||||
@@ -65,7 +65,6 @@ function CreditNoteNumberDialogContent({
|
|||||||
const handleChange = (values) => {
|
const handleChange = (values) => {
|
||||||
setReferenceFormValues(values);
|
setReferenceFormValues(values);
|
||||||
};
|
};
|
||||||
|
|
||||||
// Description.
|
// Description.
|
||||||
const description =
|
const description =
|
||||||
referenceFormValues?.incrementMode === 'auto'
|
referenceFormValues?.incrementMode === 'auto'
|
||||||
|
|||||||
@@ -8,7 +8,6 @@ import { useCustomerOpeningBalanceContext } from './CustomerOpeningBalanceFormPr
|
|||||||
import withDialogActions from '@/containers/Dialog/withDialogActions';
|
import withDialogActions from '@/containers/Dialog/withDialogActions';
|
||||||
import { compose } from '@/utils';
|
import { compose } from '@/utils';
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Customer Opening balance floating actions.
|
* Customer Opening balance floating actions.
|
||||||
* @returns
|
* @returns
|
||||||
@@ -31,6 +30,9 @@ function CustomerOpeningBalanceFormFloatingActions({
|
|||||||
return (
|
return (
|
||||||
<div className={Classes.DIALOG_FOOTER}>
|
<div className={Classes.DIALOG_FOOTER}>
|
||||||
<div className={Classes.DIALOG_FOOTER_ACTIONS}>
|
<div className={Classes.DIALOG_FOOTER_ACTIONS}>
|
||||||
|
<Button onClick={handleCancelBtnClick} style={{ minWidth: '75px' }}>
|
||||||
|
<T id={'cancel'} />
|
||||||
|
</Button>
|
||||||
<Button
|
<Button
|
||||||
intent={Intent.PRIMARY}
|
intent={Intent.PRIMARY}
|
||||||
loading={isSubmitting}
|
loading={isSubmitting}
|
||||||
@@ -39,9 +41,6 @@ function CustomerOpeningBalanceFormFloatingActions({
|
|||||||
>
|
>
|
||||||
{<T id={'edit'} />}
|
{<T id={'edit'} />}
|
||||||
</Button>
|
</Button>
|
||||||
<Button onClick={handleCancelBtnClick} style={{ minWidth: '75px' }}>
|
|
||||||
<T id={'cancel'} />
|
|
||||||
</Button>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -31,7 +31,6 @@ function InventoryAdjustmentFloatingActions({
|
|||||||
// Handle submit make adjustment button click.
|
// Handle submit make adjustment button click.
|
||||||
const handleSubmitMakeAdjustmentBtnClick = (event) => {
|
const handleSubmitMakeAdjustmentBtnClick = (event) => {
|
||||||
setSubmitPayload({ publish: true });
|
setSubmitPayload({ publish: true });
|
||||||
submitForm();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Handle close button click.
|
// Handle close button click.
|
||||||
@@ -53,7 +52,6 @@ function InventoryAdjustmentFloatingActions({
|
|||||||
<Button
|
<Button
|
||||||
loading={isSubmitting && !submitPayload.publish}
|
loading={isSubmitting && !submitPayload.publish}
|
||||||
style={{ minWidth: '75px' }}
|
style={{ minWidth: '75px' }}
|
||||||
type="submit"
|
|
||||||
onClick={handleSubmitDraftBtnClick}
|
onClick={handleSubmitDraftBtnClick}
|
||||||
>
|
>
|
||||||
{<T id={'save_as_draft'} />}
|
{<T id={'save_as_draft'} />}
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ import {
|
|||||||
transformFormToSettings,
|
transformFormToSettings,
|
||||||
transformSettingsToForm,
|
transformSettingsToForm,
|
||||||
} from '@/containers/JournalNumber/utils';
|
} from '@/containers/JournalNumber/utils';
|
||||||
|
import { DialogsName } from '@/constants/dialogs';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* invoice number dialog's content.
|
* invoice number dialog's content.
|
||||||
@@ -39,7 +40,7 @@ function InvoiceNumberDialogContent({
|
|||||||
// Handle the form success.
|
// Handle the form success.
|
||||||
const handleSuccess = () => {
|
const handleSuccess = () => {
|
||||||
setSubmitting(false);
|
setSubmitting(false);
|
||||||
closeDialog('invoice-number-form');
|
closeDialog(DialogsName.InvoiceNumberSettings);
|
||||||
onConfirm(values);
|
onConfirm(values);
|
||||||
};
|
};
|
||||||
// Handle the form errors.
|
// Handle the form errors.
|
||||||
@@ -56,10 +57,9 @@ function InvoiceNumberDialogContent({
|
|||||||
// Save the settings.
|
// Save the settings.
|
||||||
saveSettings({ options }).then(handleSuccess).catch(handleErrors);
|
saveSettings({ options }).then(handleSuccess).catch(handleErrors);
|
||||||
};
|
};
|
||||||
|
|
||||||
// Handle the dialog close.
|
// Handle the dialog close.
|
||||||
const handleClose = () => {
|
const handleClose = () => {
|
||||||
closeDialog('invoice-number-form');
|
closeDialog(DialogsName.InvoiceNumberSettings);
|
||||||
};
|
};
|
||||||
// Handle form change.
|
// Handle form change.
|
||||||
const handleChange = (values) => {
|
const handleChange = (values) => {
|
||||||
@@ -71,17 +71,19 @@ function InvoiceNumberDialogContent({
|
|||||||
? intl.get('invoice.auto_increment.auto')
|
? intl.get('invoice.auto_increment.auto')
|
||||||
: intl.get('invoice.auto_increment.manually');
|
: intl.get('invoice.auto_increment.manually');
|
||||||
|
|
||||||
|
const initialFormValues = {
|
||||||
|
...transformSettingsToForm({
|
||||||
|
nextNumber,
|
||||||
|
numberPrefix,
|
||||||
|
autoIncrement,
|
||||||
|
}),
|
||||||
|
...initialValues,
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<InvoiceNumberDialogProvider>
|
<InvoiceNumberDialogProvider>
|
||||||
<ReferenceNumberForm
|
<ReferenceNumberForm
|
||||||
initialValues={{
|
initialValues={initialFormValues}
|
||||||
...transformSettingsToForm({
|
|
||||||
nextNumber,
|
|
||||||
numberPrefix,
|
|
||||||
autoIncrement,
|
|
||||||
}),
|
|
||||||
...initialValues,
|
|
||||||
}}
|
|
||||||
description={description}
|
description={description}
|
||||||
onSubmit={handleSubmitForm}
|
onSubmit={handleSubmitForm}
|
||||||
onClose={handleClose}
|
onClose={handleClose}
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ export const getDefaultGeneralLedgerQuery = () => {
|
|||||||
return {
|
return {
|
||||||
fromDate: moment().startOf('year').format('YYYY-MM-DD'),
|
fromDate: moment().startOf('year').format('YYYY-MM-DD'),
|
||||||
toDate: moment().endOf('year').format('YYYY-MM-DD'),
|
toDate: moment().endOf('year').format('YYYY-MM-DD'),
|
||||||
basis: 'accural',
|
basis: 'accrual',
|
||||||
filterByOption: 'with-transactions',
|
filterByOption: 'with-transactions',
|
||||||
branchesIds: [],
|
branchesIds: [],
|
||||||
accountsIds: [],
|
accountsIds: [],
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ export const getDefaultJournalQuery = () => {
|
|||||||
return {
|
return {
|
||||||
fromDate: moment().startOf('year').format('YYYY-MM-DD'),
|
fromDate: moment().startOf('year').format('YYYY-MM-DD'),
|
||||||
toDate: moment().endOf('year').format('YYYY-MM-DD'),
|
toDate: moment().endOf('year').format('YYYY-MM-DD'),
|
||||||
basis: 'accural',
|
basis: 'accrual',
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ export default function RadiosAccountingBasis(props) {
|
|||||||
{...rest}
|
{...rest}
|
||||||
>
|
>
|
||||||
<Radio label={intl.get('cash')} value="cash" />
|
<Radio label={intl.get('cash')} value="cash" />
|
||||||
<Radio label={intl.get('accrual')} value="accural" />
|
<Radio label={intl.get('accrual')} value="accrual" />
|
||||||
</RadioGroup>
|
</RadioGroup>
|
||||||
)}
|
)}
|
||||||
</FastField>
|
</FastField>
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ export function getDefaultTrialBalanceQuery() {
|
|||||||
return {
|
return {
|
||||||
fromDate: moment().startOf('year').format('YYYY-MM-DD'),
|
fromDate: moment().startOf('year').format('YYYY-MM-DD'),
|
||||||
toDate: moment().endOf('year').format('YYYY-MM-DD'),
|
toDate: moment().endOf('year').format('YYYY-MM-DD'),
|
||||||
basis: 'accural',
|
basis: 'accrual',
|
||||||
filterByOption: 'with-transactions',
|
filterByOption: 'with-transactions',
|
||||||
branchesIds: [],
|
branchesIds: [],
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ export default function ItemFormFloatingActions({ onCancel }) {
|
|||||||
const { setSubmitPayload, isNewMode } = useItemFormContext();
|
const { setSubmitPayload, isNewMode } = useItemFormContext();
|
||||||
|
|
||||||
// Formik context.
|
// Formik context.
|
||||||
const { isSubmitting } = useFormikContext();
|
const { isSubmitting, submitForm } = useFormikContext();
|
||||||
|
|
||||||
// Handle cancel button click.
|
// Handle cancel button click.
|
||||||
const handleCancelBtnClick = (event) => {
|
const handleCancelBtnClick = (event) => {
|
||||||
@@ -33,6 +33,7 @@ export default function ItemFormFloatingActions({ onCancel }) {
|
|||||||
// Handle submit & new button click.
|
// Handle submit & new button click.
|
||||||
const handleSubmitAndNewBtnClick = (event) => {
|
const handleSubmitAndNewBtnClick = (event) => {
|
||||||
setSubmitPayload({ redirect: false });
|
setSubmitPayload({ redirect: false });
|
||||||
|
submitForm();
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -52,7 +53,6 @@ export default function ItemFormFloatingActions({ onCancel }) {
|
|||||||
className={classNames('ml1', 'btn--submit-new')}
|
className={classNames('ml1', 'btn--submit-new')}
|
||||||
disabled={isSubmitting}
|
disabled={isSubmitting}
|
||||||
onClick={handleSubmitAndNewBtnClick}
|
onClick={handleSubmitAndNewBtnClick}
|
||||||
type="submit"
|
|
||||||
>
|
>
|
||||||
<T id={'save_new'} />
|
<T id={'save_new'} />
|
||||||
</Button>
|
</Button>
|
||||||
|
|||||||
@@ -2,49 +2,49 @@
|
|||||||
import React, { useMemo } from 'react';
|
import React, { useMemo } from 'react';
|
||||||
import * as Yup from 'yup';
|
import * as Yup from 'yup';
|
||||||
import { Formik, Form } from 'formik';
|
import { Formik, Form } from 'formik';
|
||||||
import { FormattedMessage as T } from '@/components';
|
|
||||||
import { Intent, Button, Classes } from '@blueprintjs/core';
|
import { Intent, Button, Classes } from '@blueprintjs/core';
|
||||||
|
|
||||||
import '@/style/pages/ReferenceNumber/ReferenceNumber.scss';
|
import '@/style/pages/ReferenceNumber/ReferenceNumber.scss';
|
||||||
|
|
||||||
import { FormObserver } from '@/components';
|
import { FormattedMessage as T, FormObserver } from '@/components';
|
||||||
import ReferenceNumberFormContent from './ReferenceNumberFormContent';
|
import ReferenceNumberFormContent from './ReferenceNumberFormContent';
|
||||||
import { transformValuesToForm } from './utils';
|
import { transformValuesToForm } from './utils';
|
||||||
import { saveInvoke } from '@/utils';
|
import { saveInvoke, transformToForm } from '@/utils';
|
||||||
|
|
||||||
|
const initialFormValues = {
|
||||||
|
incrementMode: 'auto',
|
||||||
|
numberPrefix: '',
|
||||||
|
nextNumber: '',
|
||||||
|
onceManualNumber: '',
|
||||||
|
};
|
||||||
|
|
||||||
|
// Validation schema.
|
||||||
|
const validationSchema = Yup.object().shape({
|
||||||
|
incrementMode: Yup.string(),
|
||||||
|
numberPrefix: Yup.string(),
|
||||||
|
nextNumber: Yup.number(),
|
||||||
|
onceManualNumber: Yup.string(),
|
||||||
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reference number form.
|
* Reference number form.
|
||||||
*/
|
*/
|
||||||
export default function ReferenceNumberForm({
|
export default function ReferenceNumberForm({
|
||||||
onSubmit,
|
|
||||||
onClose,
|
|
||||||
initialValues,
|
initialValues,
|
||||||
description,
|
description,
|
||||||
|
onSubmit,
|
||||||
|
onClose,
|
||||||
onChange,
|
onChange,
|
||||||
}) {
|
}) {
|
||||||
// Validation schema.
|
|
||||||
const validationSchema = Yup.object().shape({
|
|
||||||
incrementMode: Yup.string(),
|
|
||||||
numberPrefix: Yup.string(),
|
|
||||||
nextNumber: Yup.number(),
|
|
||||||
manualTransactionNo: Yup.string(),
|
|
||||||
});
|
|
||||||
// Initial values.
|
// Initial values.
|
||||||
const formInitialValues = useMemo(
|
const formInitialValues = {
|
||||||
() => ({
|
...initialFormValues,
|
||||||
...initialValues,
|
...transformToForm(initialValues, initialFormValues),
|
||||||
incrementMode:
|
};
|
||||||
initialValues.incrementMode === 'auto' &&
|
|
||||||
initialValues.manualTransactionNo
|
|
||||||
? 'manual-transaction'
|
|
||||||
: initialValues.incrementMode,
|
|
||||||
}),
|
|
||||||
[initialValues],
|
|
||||||
);
|
|
||||||
// Handle the form submit.
|
// Handle the form submit.
|
||||||
const handleSubmit = (values, methods) => {
|
const handleSubmit = (values, methods) => {
|
||||||
const parsed = transformValuesToForm(values);
|
const parsed = transformValuesToForm(values);
|
||||||
saveInvoke(onSubmit, { ...parsed, ...values }, methods);
|
saveInvoke(onSubmit, { ...values, ...parsed }, methods);
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -1,17 +1,15 @@
|
|||||||
// @ts-nocheck
|
// @ts-nocheck
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { FastField, useFormikContext } from 'formik';
|
import { FastField, useFormikContext } from 'formik';
|
||||||
import { FormattedMessage as T } from '@/components';
|
|
||||||
import { FormGroup, InputGroup, Radio } from '@blueprintjs/core';
|
import { FormGroup, InputGroup, Radio } from '@blueprintjs/core';
|
||||||
import { If, Row, Col, ErrorMessage } from '@/components';
|
|
||||||
|
import { FormattedMessage as T, Row, Col, ErrorMessage } from '@/components';
|
||||||
import { inputIntent } from '@/utils';
|
import { inputIntent } from '@/utils';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reference number form content.
|
* Reference number form content.
|
||||||
*/
|
*/
|
||||||
export default function ReferenceNumberFormContent() {
|
export default function ReferenceNumberFormContent() {
|
||||||
const { values } = useFormikContext();
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{/* ------------- Auto increment mode ------------- */}
|
{/* ------------- Auto increment mode ------------- */}
|
||||||
@@ -27,54 +25,13 @@ export default function ReferenceNumberFormContent() {
|
|||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</FastField>
|
</FastField>
|
||||||
|
<ReferenceNumberAutoIncrement />
|
||||||
<If condition={values.incrementMode === 'auto'}>
|
|
||||||
<Row>
|
|
||||||
{/* ------------- Prefix ------------- */}
|
|
||||||
<Col xs={4}>
|
|
||||||
<FastField name={'numberPrefix'}>
|
|
||||||
{({ form, field, meta: { error, touched } }) => (
|
|
||||||
<FormGroup
|
|
||||||
label={<T id={'prefix'} />}
|
|
||||||
className={'form-group--'}
|
|
||||||
intent={inputIntent({ error, touched })}
|
|
||||||
helperText={<ErrorMessage name={'numberPrefix'} />}
|
|
||||||
>
|
|
||||||
<InputGroup
|
|
||||||
intent={inputIntent({ error, touched })}
|
|
||||||
{...field}
|
|
||||||
/>
|
|
||||||
</FormGroup>
|
|
||||||
)}
|
|
||||||
</FastField>
|
|
||||||
</Col>
|
|
||||||
|
|
||||||
{/* ------------- Next number ------------- */}
|
|
||||||
<Col xs={6}>
|
|
||||||
<FastField name={'nextNumber'}>
|
|
||||||
{({ form, field, meta: { error, touched } }) => (
|
|
||||||
<FormGroup
|
|
||||||
label={<T id={'next_number'} />}
|
|
||||||
className={'form-group--next-number'}
|
|
||||||
intent={inputIntent({ error, touched })}
|
|
||||||
helperText={<ErrorMessage name={'nextNumber'} />}
|
|
||||||
>
|
|
||||||
<InputGroup
|
|
||||||
intent={inputIntent({ error, touched })}
|
|
||||||
{...field}
|
|
||||||
/>
|
|
||||||
</FormGroup>
|
|
||||||
)}
|
|
||||||
</FastField>
|
|
||||||
</Col>
|
|
||||||
</Row>
|
|
||||||
</If>
|
|
||||||
|
|
||||||
{/* ------------- Manual increment mode ------------- */}
|
{/* ------------- Manual increment mode ------------- */}
|
||||||
<FastField name={'incrementMode'}>
|
<FastField name={'incrementMode'}>
|
||||||
{({ form, field, meta: { error, touched } }) => (
|
{({ form, field, meta: { error, touched } }) => (
|
||||||
<Radio
|
<Radio
|
||||||
label={<T id={'auto_increment.field.manual_this_transaction'} />}
|
label={<T id={'auto_increment.field.manually'} />}
|
||||||
value="manual"
|
value="manual"
|
||||||
onChange={() => {
|
onChange={() => {
|
||||||
form.setFieldValue('incrementMode', 'manual');
|
form.setFieldValue('incrementMode', 'manual');
|
||||||
@@ -85,20 +42,70 @@ export default function ReferenceNumberFormContent() {
|
|||||||
</FastField>
|
</FastField>
|
||||||
|
|
||||||
{/* ------------- Transaction manual increment mode ------------- */}
|
{/* ------------- Transaction manual increment mode ------------- */}
|
||||||
<If condition={values.manualTransactionNo}>
|
<ReferenceNumberManualOnce />
|
||||||
<FastField name={'incrementMode'}>
|
|
||||||
{({ form, field, meta: { error, touched } }) => (
|
|
||||||
<Radio
|
|
||||||
label={<T id={'auto_increment.field.manually'} />}
|
|
||||||
value="manual"
|
|
||||||
onChange={() => {
|
|
||||||
form.setFieldValue('incrementMode', 'manual-transaction');
|
|
||||||
}}
|
|
||||||
checked={field.value === 'manual-transaction'}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</FastField>
|
|
||||||
</If>
|
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function ReferenceNumberAutoIncrement() {
|
||||||
|
const { values } = useFormikContext();
|
||||||
|
if (!values.incrementMode === 'auto') return null;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Row>
|
||||||
|
{/* ------------- Prefix ------------- */}
|
||||||
|
<Col xs={4}>
|
||||||
|
<FastField name={'numberPrefix'}>
|
||||||
|
{({ form, field, meta: { error, touched } }) => (
|
||||||
|
<FormGroup
|
||||||
|
label={<T id={'prefix'} />}
|
||||||
|
className={'form-group--'}
|
||||||
|
intent={inputIntent({ error, touched })}
|
||||||
|
helperText={<ErrorMessage name={'numberPrefix'} />}
|
||||||
|
>
|
||||||
|
<InputGroup intent={inputIntent({ error, touched })} {...field} />
|
||||||
|
</FormGroup>
|
||||||
|
)}
|
||||||
|
</FastField>
|
||||||
|
</Col>
|
||||||
|
|
||||||
|
{/* ------------- Next number ------------- */}
|
||||||
|
<Col xs={6}>
|
||||||
|
<FastField name={'nextNumber'}>
|
||||||
|
{({ form, field, meta: { error, touched } }) => (
|
||||||
|
<FormGroup
|
||||||
|
label={<T id={'next_number'} />}
|
||||||
|
className={'form-group--next-number'}
|
||||||
|
intent={inputIntent({ error, touched })}
|
||||||
|
helperText={<ErrorMessage name={'nextNumber'} />}
|
||||||
|
>
|
||||||
|
<InputGroup intent={inputIntent({ error, touched })} {...field} />
|
||||||
|
</FormGroup>
|
||||||
|
)}
|
||||||
|
</FastField>
|
||||||
|
</Col>
|
||||||
|
</Row>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function ReferenceNumberManualOnce() {
|
||||||
|
const { values } = useFormikContext();
|
||||||
|
|
||||||
|
// Do not show the field if the one manual transaction number is not presented.
|
||||||
|
if (!values.onceManualNumber) return null;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<FastField name={'incrementMode'}>
|
||||||
|
{({ form, field, meta: { error, touched } }) => (
|
||||||
|
<Radio
|
||||||
|
label={<T id={'auto_increment.field.manual_this_transaction'} />}
|
||||||
|
value="manual"
|
||||||
|
onChange={() => {
|
||||||
|
form.setFieldValue('incrementMode', 'manual-transaction');
|
||||||
|
}}
|
||||||
|
checked={field.value === 'manual-transaction'}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</FastField>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import {
|
|||||||
transfromToSnakeCase,
|
transfromToSnakeCase,
|
||||||
transactionNumber,
|
transactionNumber,
|
||||||
} from '@/utils';
|
} from '@/utils';
|
||||||
|
import { omit } from 'lodash';
|
||||||
|
|
||||||
export const defaultInvoiceNoSettings = {
|
export const defaultInvoiceNoSettings = {
|
||||||
nextNumber: '',
|
nextNumber: '',
|
||||||
@@ -13,8 +14,8 @@ export const defaultInvoiceNoSettings = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const transformSettingsToForm = (settings) => ({
|
export const transformSettingsToForm = (settings) => ({
|
||||||
...settings,
|
...omit(settings, ['autoIncrement']),
|
||||||
incrementMode: settings.autoIncrement === 'true' ? 'auto' : 'manual',
|
incrementMode: settings.autoIncrement ? 'auto' : 'manual',
|
||||||
});
|
});
|
||||||
|
|
||||||
export const transformFormToSettings = (values, group) => {
|
export const transformFormToSettings = (values, group) => {
|
||||||
@@ -25,13 +26,21 @@ export const transformFormToSettings = (values, group) => {
|
|||||||
return optionsMapToArray(options).map((option) => ({ ...option, group }));
|
return optionsMapToArray(options).map((option) => ({ ...option, group }));
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Transaction number returns auto-increment if the increment mode is auto or
|
||||||
|
* returns empty string if the increment mode is manually or returns the entered
|
||||||
|
* manual text if the increment mode is manual once just in this transaction.
|
||||||
|
*/
|
||||||
export const transformValuesToForm = (values) => {
|
export const transformValuesToForm = (values) => {
|
||||||
const incrementNumber =
|
const autoIncrementNumber = transactionNumber(
|
||||||
|
values.numberPrefix,
|
||||||
|
values.nextNumber,
|
||||||
|
);
|
||||||
|
const _transactionNumber =
|
||||||
values.incrementMode === 'auto'
|
values.incrementMode === 'auto'
|
||||||
? transactionNumber(values.numberPrefix, values.nextNumber)
|
? autoIncrementNumber
|
||||||
: values.manualTransactionNo;
|
: values.incrementMode === 'manual-transaction'
|
||||||
|
? values.onceManualNumber
|
||||||
const manually = values.incrementMode === 'auto' ? false : true;
|
: '';
|
||||||
|
return { transactionNumber: _transactionNumber };
|
||||||
return { incrementNumber, manually };
|
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -2,12 +2,18 @@
|
|||||||
import * as Yup from 'yup';
|
import * as Yup from 'yup';
|
||||||
|
|
||||||
const Schema = Yup.object().shape({
|
const Schema = Yup.object().shape({
|
||||||
accounting_basis: Yup.string().required(),
|
organization: Yup.object({
|
||||||
account_code_required: Yup.boolean().nullable(),
|
accountingBasis: Yup.string().required(),
|
||||||
account_code_unique: Yup.boolean().nullable(),
|
}),
|
||||||
withdrawal_account: Yup.number().nullable(),
|
accounts: Yup.object({
|
||||||
preferred_deposit_account: Yup.number().nullable(),
|
accountCodeRequired: Yup.boolean().nullable(),
|
||||||
preferred_advance_deposit: Yup.number().nullable(),
|
accountCodeUnique: Yup.boolean().nullable(),
|
||||||
|
}),
|
||||||
|
paymentReceives: Yup.object({
|
||||||
|
preferredDepositAccount: Yup.number().nullable(),
|
||||||
|
preferredAdvanceDeposit: Yup.number().nullable(),
|
||||||
|
withdrawalAccount: Yup.number().nullable(),
|
||||||
|
})
|
||||||
});
|
});
|
||||||
|
|
||||||
export const AccountantSchema = Schema;
|
export const AccountantSchema = Schema;
|
||||||
|
|||||||
@@ -1,16 +1,9 @@
|
|||||||
// @ts-nocheck
|
// @ts-nocheck
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import intl from 'react-intl-universal';
|
import intl from 'react-intl-universal';
|
||||||
import { Form, FastField, useFormikContext } from 'formik';
|
import { Form, useFormikContext } from 'formik';
|
||||||
import styled from 'styled-components';
|
import styled from 'styled-components';
|
||||||
import {
|
import { FormGroup, Radio, Button, Intent } from '@blueprintjs/core';
|
||||||
FormGroup,
|
|
||||||
RadioGroup,
|
|
||||||
Radio,
|
|
||||||
Checkbox,
|
|
||||||
Button,
|
|
||||||
Intent,
|
|
||||||
} from '@blueprintjs/core';
|
|
||||||
import { useHistory } from 'react-router-dom';
|
import { useHistory } from 'react-router-dom';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
@@ -19,8 +12,9 @@ import {
|
|||||||
FieldRequiredHint,
|
FieldRequiredHint,
|
||||||
CardFooterActions,
|
CardFooterActions,
|
||||||
FFormGroup,
|
FFormGroup,
|
||||||
|
FCheckbox,
|
||||||
|
FRadioGroup,
|
||||||
} from '@/components';
|
} from '@/components';
|
||||||
import { handleStringChange, inputIntent } from '@/utils';
|
|
||||||
import { ACCOUNT_PARENT_TYPE, ACCOUNT_TYPE } from '@/constants/accountTypes';
|
import { ACCOUNT_PARENT_TYPE, ACCOUNT_TYPE } from '@/constants/accountTypes';
|
||||||
import { useAccountantFormContext } from './AccountantFormProvider';
|
import { useAccountantFormContext } from './AccountantFormProvider';
|
||||||
|
|
||||||
@@ -30,7 +24,6 @@ import { useAccountantFormContext } from './AccountantFormProvider';
|
|||||||
export default function AccountantForm() {
|
export default function AccountantForm() {
|
||||||
const history = useHistory();
|
const history = useHistory();
|
||||||
const { accounts } = useAccountantFormContext();
|
const { accounts } = useAccountantFormContext();
|
||||||
|
|
||||||
const { isSubmitting } = useFormikContext();
|
const { isSubmitting } = useFormikContext();
|
||||||
|
|
||||||
const handleCloseClick = () => {
|
const handleCloseClick = () => {
|
||||||
@@ -48,78 +41,54 @@ export default function AccountantForm() {
|
|||||||
}
|
}
|
||||||
className={'accounts-checkbox'}
|
className={'accounts-checkbox'}
|
||||||
>
|
>
|
||||||
{/*------------ Account code (required) -----------*/}
|
{/*------------ Account Code (required) -----------*/}
|
||||||
<FastField name={'account_code_required'} type={'checkbox'}>
|
<FFormGroup inline={true} name={'accounts.accountCodeRequired'}>
|
||||||
{({ field }) => (
|
<FCheckbox
|
||||||
<FormGroup inline={true}>
|
inline={true}
|
||||||
<Checkbox
|
label={
|
||||||
inline={true}
|
<T id={'make_account_code_required_when_create_a_new_accounts'} />
|
||||||
label={
|
}
|
||||||
<T
|
name={'accounts.accountCodeRequired'}
|
||||||
id={'make_account_code_required_when_create_a_new_accounts'}
|
/>
|
||||||
/>
|
</FFormGroup>
|
||||||
}
|
|
||||||
name={'account_code_required'}
|
|
||||||
{...field}
|
|
||||||
/>
|
|
||||||
</FormGroup>
|
|
||||||
)}
|
|
||||||
</FastField>
|
|
||||||
|
|
||||||
{/*------------ Account code (unique) -----------*/}
|
{/*------------ Account Code (unique) -----------*/}
|
||||||
<FastField name={'account_code_unique'} type={'checkbox'}>
|
<FFormGroup
|
||||||
{({ field }) => (
|
name={'accounts.accountCodeUnique'}
|
||||||
<FormGroup inline={true}>
|
type={'checkbox'}
|
||||||
<Checkbox
|
inline={true}
|
||||||
inline={true}
|
>
|
||||||
label={
|
<FCheckbox
|
||||||
<T
|
inline={true}
|
||||||
id={
|
label={
|
||||||
'should_account_code_be_unique_when_create_a_new_account'
|
<T
|
||||||
}
|
id={'should_account_code_be_unique_when_create_a_new_account'}
|
||||||
/>
|
|
||||||
}
|
|
||||||
name={'account_code_unique'}
|
|
||||||
{...field}
|
|
||||||
/>
|
/>
|
||||||
</FormGroup>
|
}
|
||||||
)}
|
name={'accounts.accountCodeUnique'}
|
||||||
</FastField>
|
/>
|
||||||
|
</FFormGroup>
|
||||||
</FormGroup>
|
</FormGroup>
|
||||||
|
|
||||||
{/* ----------- Accounting basis ----------- */}
|
{/* ----------- Accounting Basis ----------- */}
|
||||||
<FastField name={'accounting_basis'}>
|
<FormGroup
|
||||||
{({
|
name={'organization.accountingBasis'}
|
||||||
form: { setFieldValue },
|
labelInfo={<FieldRequiredHint />}
|
||||||
field: { value },
|
label={
|
||||||
meta: { error, touched },
|
<strong>
|
||||||
}) => (
|
<T id={'accounting_basis_'} />
|
||||||
<FormGroup
|
</strong>
|
||||||
labelInfo={<FieldRequiredHint />}
|
}
|
||||||
intent={inputIntent({ error, touched })}
|
>
|
||||||
label={
|
<FRadioGroup name={'organization.accountingBasis'} inline={true}>
|
||||||
<strong>
|
<Radio label={intl.get('cash')} value="cash" />
|
||||||
<T id={'accounting_basis_'} />
|
<Radio label={intl.get('accrual')} value="accrual" />
|
||||||
</strong>
|
</FRadioGroup>
|
||||||
}
|
</FormGroup>
|
||||||
>
|
|
||||||
<RadioGroup
|
|
||||||
inline={true}
|
|
||||||
selectedValue={value}
|
|
||||||
onChange={handleStringChange((_value) => {
|
|
||||||
setFieldValue('accounting_basis', _value);
|
|
||||||
})}
|
|
||||||
>
|
|
||||||
<Radio label={intl.get('cash')} value="cash" />
|
|
||||||
<Radio label={intl.get('accrual')} value="accrual" />
|
|
||||||
</RadioGroup>
|
|
||||||
</FormGroup>
|
|
||||||
)}
|
|
||||||
</FastField>
|
|
||||||
|
|
||||||
{/* ----------- Deposit customer account ----------- */}
|
{/* ----------- Deposit Customer Account ----------- */}
|
||||||
<AccountantFormGroup
|
<AccountantFormGroup
|
||||||
name={'preferred_deposit_account'}
|
name={'paymentReceives.preferredDepositAccount'}
|
||||||
label={
|
label={
|
||||||
<strong>
|
<strong>
|
||||||
<T id={'deposit_customer_account'} />
|
<T id={'deposit_customer_account'} />
|
||||||
@@ -136,7 +105,7 @@ export default function AccountantForm() {
|
|||||||
fastField={true}
|
fastField={true}
|
||||||
>
|
>
|
||||||
<AccountsSelect
|
<AccountsSelect
|
||||||
name={'preferred_deposit_account'}
|
name={'paymentReceives.preferredDepositAccount'}
|
||||||
items={accounts}
|
items={accounts}
|
||||||
placeholder={<T id={'select_payment_account'} />}
|
placeholder={<T id={'select_payment_account'} />}
|
||||||
filterByTypes={[
|
filterByTypes={[
|
||||||
@@ -148,9 +117,9 @@ export default function AccountantForm() {
|
|||||||
/>
|
/>
|
||||||
</AccountantFormGroup>
|
</AccountantFormGroup>
|
||||||
|
|
||||||
{/* ----------- Withdrawal vendor account ----------- */}
|
{/* ----------- Withdrawal Vendor Account ----------- */}
|
||||||
<AccountantFormGroup
|
<AccountantFormGroup
|
||||||
name={'withdrawal_account'}
|
name={'billPayments.withdrawalAccount'}
|
||||||
label={
|
label={
|
||||||
<strong>
|
<strong>
|
||||||
<T id={'withdrawal_vendor_account'} />
|
<T id={'withdrawal_vendor_account'} />
|
||||||
@@ -167,7 +136,7 @@ export default function AccountantForm() {
|
|||||||
fastField={true}
|
fastField={true}
|
||||||
>
|
>
|
||||||
<AccountsSelect
|
<AccountsSelect
|
||||||
name={'withdrawal_account'}
|
name={'billPayments.withdrawalAccount'}
|
||||||
items={accounts}
|
items={accounts}
|
||||||
placeholder={<T id={'select_payment_account'} />}
|
placeholder={<T id={'select_payment_account'} />}
|
||||||
filterByTypes={[
|
filterByTypes={[
|
||||||
@@ -179,9 +148,9 @@ export default function AccountantForm() {
|
|||||||
/>
|
/>
|
||||||
</AccountantFormGroup>
|
</AccountantFormGroup>
|
||||||
|
|
||||||
{/* ----------- Withdrawal customer account ----------- */}
|
{/* ----------- Withdrawal Customer Account ----------- */}
|
||||||
<AccountantFormGroup
|
<AccountantFormGroup
|
||||||
name={'preferred_advance_deposit'}
|
name={'paymentReceives.preferredAdvanceDeposit'}
|
||||||
label={
|
label={
|
||||||
<strong>
|
<strong>
|
||||||
<T id={'customer_advance_deposit'} />
|
<T id={'customer_advance_deposit'} />
|
||||||
@@ -198,7 +167,7 @@ export default function AccountantForm() {
|
|||||||
fastField={true}
|
fastField={true}
|
||||||
>
|
>
|
||||||
<AccountsSelect
|
<AccountsSelect
|
||||||
name={'preferred_advance_deposit'}
|
name={'paymentReceives.preferredAdvanceDeposit'}
|
||||||
items={accounts}
|
items={accounts}
|
||||||
placeholder={<T id={'select_payment_account'} />}
|
placeholder={<T id={'select_payment_account'} />}
|
||||||
filterByParentTypes={[ACCOUNT_PARENT_TYPE.CURRENT_ASSET]}
|
filterByParentTypes={[ACCOUNT_PARENT_TYPE.CURRENT_ASSET]}
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user