Compare commits
2 Commits
attachment
...
v0.16.14
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2ada57a2b4 | ||
|
|
e380c598d3 |
@@ -1,4 +1,4 @@
|
||||
import { difference } from 'lodash';
|
||||
import { difference, isEmpty } from 'lodash';
|
||||
import { Service, Inject } from 'typedi';
|
||||
import { ServiceError } from '@/exceptions';
|
||||
import {
|
||||
@@ -244,16 +244,12 @@ export class CommandManualJournalValidators {
|
||||
/**
|
||||
* Validates the manual journal number require.
|
||||
* @param {string} journalNumber
|
||||
* @throws {ServiceError(ERRORS.MANUAL_JOURNAL_NO_REQUIRED)}
|
||||
*/
|
||||
public validateJournalNoRequireWhenAutoNotEnabled = (
|
||||
tenantId: number,
|
||||
journalNumber: string
|
||||
) => {
|
||||
// Retrieve the next manual journal number.
|
||||
const autoIncrmenetEnabled =
|
||||
this.autoIncrement.autoIncrementEnabled(tenantId);
|
||||
|
||||
if (!journalNumber || !autoIncrmenetEnabled) {
|
||||
if (isEmpty(journalNumber)) {
|
||||
throw new ServiceError(ERRORS.MANUAL_JOURNAL_NO_REQUIRED);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -99,7 +99,6 @@ export class CreateManualJournalService {
|
||||
|
||||
// Validate manual journal number require when auto-increment not enabled.
|
||||
this.validator.validateJournalNoRequireWhenAutoNotEnabled(
|
||||
tenantId,
|
||||
manualJournalDTO.journalNumber
|
||||
);
|
||||
// Validate manual journal uniquiness on the storage.
|
||||
|
||||
@@ -15,10 +15,8 @@ export default class AutoIncrementOrdersService {
|
||||
const group = settingsGroup;
|
||||
|
||||
// Settings service transaction number and prefix.
|
||||
const autoIncrement = settings.get({ group, key: 'auto_increment' }, false);
|
||||
|
||||
return parseBoolean(autoIncrement, false);
|
||||
}
|
||||
return settings.get({ group, key: 'auto_increment' }, false);
|
||||
};
|
||||
|
||||
/**
|
||||
* Retrieve the next service transaction number.
|
||||
@@ -27,17 +25,16 @@ export default class AutoIncrementOrdersService {
|
||||
* @param {Function} getMaxTransactionNo
|
||||
* @return {Promise<string>}
|
||||
*/
|
||||
getNextTransactionNumber(tenantId: number, settingsGroup: string): string {
|
||||
getNextTransactionNumber(tenantId: number, group: string): string {
|
||||
const settings = this.tenancy.settings(tenantId);
|
||||
const group = settingsGroup;
|
||||
|
||||
// Settings service transaction number and prefix.
|
||||
const autoIncrement = settings.get({ group, key: 'auto_increment' }, false);
|
||||
const autoIncrement = this.autoIncrementEnabled(tenantId, group);
|
||||
|
||||
const settingNo = settings.get({ group, key: 'next_number' }, '');
|
||||
const settingPrefix = settings.get({ group, key: 'number_prefix' }, '');
|
||||
|
||||
return parseBoolean(autoIncrement, false) ? `${settingPrefix}${settingNo}` : '';
|
||||
return autoIncrement ? `${settingPrefix}${settingNo}` : '';
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -53,7 +50,9 @@ export default class AutoIncrementOrdersService {
|
||||
const autoIncrement = settings.get({ group, key: 'auto_increment' });
|
||||
|
||||
// Can't continue if the auto-increment of the service was disabled.
|
||||
if (!autoIncrement) { return; }
|
||||
if (!autoIncrement) {
|
||||
return;
|
||||
}
|
||||
|
||||
settings.set(
|
||||
{ group, key: 'next_number' },
|
||||
|
||||
@@ -337,6 +337,9 @@ const booleanValues: string[] = [
|
||||
].map((value) => normalizeValue(value));
|
||||
|
||||
export const parseBoolean = <T>(value: any, defaultValue: T): T | boolean => {
|
||||
if (typeof value === 'boolean') {
|
||||
return value; // Retrun early we have nothing to parse.
|
||||
}
|
||||
const normalizedValue = normalizeValue(value);
|
||||
if (isEmpty(value) || booleanValues.indexOf(normalizedValue) === -1) {
|
||||
return defaultValue;
|
||||
|
||||
@@ -9,7 +9,11 @@ import AuthInsider from '@/containers/Authentication/AuthInsider';
|
||||
import { useAuthLogin, useAuthRegister } from '@/hooks/query/authentication';
|
||||
|
||||
import RegisterForm from './RegisterForm';
|
||||
import { RegisterSchema, transformRegisterErrorsToForm, transformRegisterToastMessages } from './utils';
|
||||
import {
|
||||
RegisterSchema,
|
||||
transformRegisterErrorsToForm,
|
||||
transformRegisterToastMessages,
|
||||
} from './utils';
|
||||
import {
|
||||
AuthFooterLinks,
|
||||
AuthFooterLink,
|
||||
@@ -32,7 +36,7 @@ export default function RegisterUserForm() {
|
||||
|
||||
const handleSubmit = (values, { setSubmitting, setErrors }) => {
|
||||
authRegisterMutate(values)
|
||||
.then((response) => {
|
||||
.then(() => {
|
||||
authLoginMutate({
|
||||
crediential: values.email,
|
||||
password: values.password,
|
||||
@@ -87,7 +91,10 @@ function RegisterFooterLinks() {
|
||||
return (
|
||||
<AuthFooterLinks>
|
||||
<AuthFooterLink>
|
||||
<T id={'return_to'} /> <Link to={'/auth/login'}><T id={'sign_in'} /></Link>
|
||||
<T id={'return_to'} />{' '}
|
||||
<Link to={'/auth/login'}>
|
||||
<T id={'sign_in'} />
|
||||
</Link>
|
||||
</AuthFooterLink>
|
||||
|
||||
<AuthFooterLink>
|
||||
|
||||
@@ -4,7 +4,7 @@ import AuthInsider from './AuthInsider';
|
||||
import { AuthInsiderCard } from './_components';
|
||||
import styles from './RegisterVerify.module.scss';
|
||||
import { AppToaster, Stack } from '@/components';
|
||||
import { useAuthActions } from '@/hooks/state';
|
||||
import { useAuthActions, useAuthUserVerifyEmail } from '@/hooks/state';
|
||||
import { useAuthSignUpVerifyResendMail } from '@/hooks/query';
|
||||
import { AuthContainer } from './AuthContainer';
|
||||
|
||||
@@ -13,6 +13,8 @@ export default function RegisterVerify() {
|
||||
const { mutateAsync: resendSignUpVerifyMail, isLoading } =
|
||||
useAuthSignUpVerifyResendMail();
|
||||
|
||||
const emailAddress = useAuthUserVerifyEmail();
|
||||
|
||||
const handleResendMailBtnClick = () => {
|
||||
resendSignUpVerifyMail()
|
||||
.then(() => {
|
||||
@@ -38,8 +40,8 @@ export default function RegisterVerify() {
|
||||
<AuthInsiderCard className={styles.root}>
|
||||
<h2 className={styles.title}>Please verify your email</h2>
|
||||
<p className={styles.description}>
|
||||
We sent an email to <strong>asdahmed@gmail.com</strong> Click the
|
||||
link inside to get started.
|
||||
We sent an email to <strong>{emailAddress}</strong> Click the link
|
||||
inside to get started.
|
||||
</p>
|
||||
|
||||
<Stack spacing={4}>
|
||||
|
||||
@@ -1,9 +1,17 @@
|
||||
// @ts-nocheck
|
||||
import { useMutation } from 'react-query';
|
||||
import { batch } from 'react-redux';
|
||||
import useApiRequest from '../useRequest';
|
||||
import { setCookie } from '../../utils';
|
||||
import { useRequestQuery } from '../useQueryRequest';
|
||||
import t from './types';
|
||||
import {
|
||||
useSetAuthToken,
|
||||
useSetAuthUserId,
|
||||
useSetLocale,
|
||||
useSetOrganizationId,
|
||||
useSetTenantId,
|
||||
} from '../state';
|
||||
|
||||
/**
|
||||
* Saves the response data to cookies.
|
||||
@@ -24,14 +32,30 @@ function setAuthLoginCookies(data) {
|
||||
export const useAuthLogin = (props) => {
|
||||
const apiRequest = useApiRequest();
|
||||
|
||||
const setAuthToken = useSetAuthToken();
|
||||
const setOrganizationId = useSetOrganizationId();
|
||||
const setUserId = useSetAuthUserId();
|
||||
const setTenantId = useSetTenantId();
|
||||
const setLocale = useSetLocale();
|
||||
|
||||
return useMutation((values) => apiRequest.post('auth/login', values), {
|
||||
select: (res) => res.data,
|
||||
onSuccess: (data) => {
|
||||
onSuccess: (res) => {
|
||||
// Set authentication cookies.
|
||||
setAuthLoginCookies(data.data);
|
||||
setAuthLoginCookies(res.data);
|
||||
|
||||
// Reboot the application.
|
||||
window.location.reload();
|
||||
batch(() => {
|
||||
// Sets the auth metadata to global state.
|
||||
setAuthToken(res.data.token);
|
||||
setOrganizationId(res.data.tenant.organization_id);
|
||||
setUserId(res.data.user.id);
|
||||
setTenantId(res.data.tenant.id);
|
||||
|
||||
if (res.data?.tenant?.metadata?.language) {
|
||||
setLocale(res.data?.tenant?.metadata?.language);
|
||||
}
|
||||
});
|
||||
props?.onSuccess && props?.onSuccess(...args);
|
||||
},
|
||||
...props,
|
||||
});
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// @ts-nocheck
|
||||
import { useEffect } from 'react';
|
||||
import { useMutation, useQueryClient } from 'react-query';
|
||||
import { useQueryTenant, useRequestQuery } from '../useQueryRequest';
|
||||
import { useRequestQuery } from '../useQueryRequest';
|
||||
import useApiRequest from '../useRequest';
|
||||
import { useSetFeatureDashboardMeta } from '../state/feature';
|
||||
import t from './types';
|
||||
@@ -143,7 +143,7 @@ export function useAuthenticatedAccount(props) {
|
||||
select: (response) => response.data.data,
|
||||
defaultData: {},
|
||||
onSuccess: (data) => {
|
||||
setEmailConfirmed(data.is_verified);
|
||||
setEmailConfirmed(data.is_verified, data.email);
|
||||
},
|
||||
...props,
|
||||
},
|
||||
|
||||
@@ -3,8 +3,13 @@ import { useDispatch, useSelector } from 'react-redux';
|
||||
import { useCallback } from 'react';
|
||||
import { isAuthenticated } from '@/store/authentication/authentication.reducer';
|
||||
import {
|
||||
setAuthTenantId,
|
||||
setAuthToken,
|
||||
setAuthUserId,
|
||||
setEmailConfirmed,
|
||||
setLogin,
|
||||
setOrganizationId,
|
||||
setLocale,
|
||||
} from '@/store/authentication/authentication.actions';
|
||||
import { useQueryClient } from 'react-query';
|
||||
import { removeCookie } from '@/utils';
|
||||
@@ -75,6 +80,14 @@ export const useAuthUserVerified = () => {
|
||||
return useSelector((state) => state.authentication.verified);
|
||||
};
|
||||
|
||||
/**
|
||||
* Retrieves the user's email address.
|
||||
* @returns {string}
|
||||
*/
|
||||
export const useAuthUserVerifyEmail = () => {
|
||||
return useSelector((state) => state.authentication.verifyEmail);
|
||||
};
|
||||
|
||||
/**
|
||||
* Sets the user's email verification status.
|
||||
*/
|
||||
@@ -82,7 +95,53 @@ export const useSetAuthEmailConfirmed = () => {
|
||||
const dispatch = useDispatch();
|
||||
|
||||
return useCallback(
|
||||
(verified?: boolean = true) => dispatch(setEmailConfirmed(verified)),
|
||||
(verified?: boolean = true, email: string) =>
|
||||
dispatch(setEmailConfirmed(verified, email)),
|
||||
[dispatch],
|
||||
);
|
||||
};
|
||||
|
||||
export const useSetOrganizationId = () => {
|
||||
const dispatch = useDispatch();
|
||||
|
||||
return useCallback(
|
||||
(organizationId: string) => dispatch(setOrganizationId(organizationId)),
|
||||
[dispatch],
|
||||
);
|
||||
};
|
||||
|
||||
export const useSetAuthToken = () => {
|
||||
const dispatch = useDispatch();
|
||||
|
||||
return useCallback(
|
||||
(authToken: string) => dispatch(setAuthToken(authToken)),
|
||||
[dispatch],
|
||||
);
|
||||
};
|
||||
|
||||
export const useSetTenantId = () => {
|
||||
const dispatch = useDispatch();
|
||||
|
||||
return useCallback(
|
||||
(tenantId: string) => dispatch(setAuthTenantId(tenantId)),
|
||||
[dispatch],
|
||||
);
|
||||
};
|
||||
|
||||
export const useSetAuthUserId = () => {
|
||||
const dispatch = useDispatch();
|
||||
|
||||
return useCallback(
|
||||
(userId: string) => dispatch(setAuthUserId(userId)),
|
||||
[dispatch],
|
||||
);
|
||||
};
|
||||
|
||||
export const useSetLocale = () => {
|
||||
const dispatch = useDispatch();
|
||||
|
||||
return useCallback(
|
||||
(locale: string) => dispatch(setLocale(locale)),
|
||||
[dispatch],
|
||||
);
|
||||
};
|
||||
|
||||
@@ -4,7 +4,27 @@ import t from '@/store/types';
|
||||
export const setLogin = () => ({ type: t.LOGIN_SUCCESS });
|
||||
export const setLogout = () => ({ type: t.LOGOUT });
|
||||
export const setStoreReset = () => ({ type: t.RESET });
|
||||
export const setEmailConfirmed = (verified?: boolean) => ({
|
||||
export const setEmailConfirmed = (verified?: boolean, email?: string) => ({
|
||||
type: t.SET_EMAIL_VERIFIED,
|
||||
action: { verified },
|
||||
action: { verified, email },
|
||||
});
|
||||
export const setOrganizationId = (organizationId: string) => ({
|
||||
type: t.SET_ORGANIZATIOIN_ID,
|
||||
action: { organizationId },
|
||||
});
|
||||
export const setAuthToken = (token: string) => ({
|
||||
type: t.SET_AUTH_TOKEN,
|
||||
action: { token },
|
||||
});
|
||||
export const setAuthTenantId = (tenantId: string) => ({
|
||||
type: t.SET_TENANT_ID,
|
||||
action: { tenantId },
|
||||
});
|
||||
export const setAuthUserId = (userId: string) => ({
|
||||
type: t.SET_USER_ID,
|
||||
action: { userId },
|
||||
});
|
||||
export const setLocale = (locale: string) => ({
|
||||
type: t.SET_LOCALE,
|
||||
action: { locale },
|
||||
});
|
||||
|
||||
@@ -9,12 +9,13 @@ import t from '@/store/types';
|
||||
|
||||
// Read stored data in cookies and merge it with the initial state.
|
||||
const initialState = {
|
||||
token: getCookie('token'),
|
||||
organizationId: getCookie('organization_id'),
|
||||
tenantId: getCookie('tenant_id'),
|
||||
userId: getCookie('authenticated_user_id'),
|
||||
locale: getCookie('locale'),
|
||||
token: getCookie('token') || null,
|
||||
organizationId: getCookie('organization_id') || null,
|
||||
tenantId: getCookie('tenant_id') || null,
|
||||
userId: getCookie('authenticated_user_id') || null,
|
||||
locale: getCookie('locale') || 'en',
|
||||
verified: true, // Let's be optimistic and assume the user's email is confirmed.
|
||||
verifyEmail: null,
|
||||
errors: [],
|
||||
};
|
||||
|
||||
@@ -36,11 +37,35 @@ const reducerInstance = createReducer(initialState, {
|
||||
|
||||
[t.SET_EMAIL_VERIFIED]: (
|
||||
state,
|
||||
payload: PayloadAction<{ verified?: boolean }>,
|
||||
payload: PayloadAction<{ verified?: boolean; email?: string }>,
|
||||
) => {
|
||||
state.verified = !isUndefined(payload.action.verified)
|
||||
? payload.action.verified
|
||||
: true;
|
||||
state.verifyEmail = payload.action.email || null;
|
||||
|
||||
if (state.verified) {
|
||||
state.verifyEmail = null;
|
||||
}
|
||||
},
|
||||
|
||||
[t.SET_AUTH_TOKEN]: (state, payload: PayloadAction<{ token: string }>) => {
|
||||
state.token = payload.action.token;
|
||||
},
|
||||
|
||||
[t.SET_ORGANIZATIOIN_ID]: (
|
||||
state,
|
||||
payload: PayloadAction<{ organizationId: string }>,
|
||||
) => {
|
||||
state.organizationId = payload.action.organizationId;
|
||||
},
|
||||
|
||||
[t.SET_TENANT_ID]: (state, payload: PayloadAction<{ tenantId: string }>) => {
|
||||
state.tenantId = payload.action.tenantId;
|
||||
},
|
||||
|
||||
[t.SET_USER_ID]: (state, payload: PayloadAction<{ userId: string }>) => {
|
||||
state.userId = payload.action.userId;
|
||||
},
|
||||
|
||||
[t.RESET]: (state) => {
|
||||
|
||||
@@ -7,5 +7,10 @@ export default {
|
||||
LOGOUT: 'LOGOUT',
|
||||
LOGIN_CLEAR_ERRORS: 'LOGIN_CLEAR_ERRORS',
|
||||
RESET: 'RESET',
|
||||
SET_EMAIL_VERIFIED: 'SET_EMAIL_VERIFIED'
|
||||
SET_EMAIL_VERIFIED: 'SET_EMAIL_VERIFIED',
|
||||
SET_AUTH_TOKEN: 'SET_AUTH_TOKEN',
|
||||
SET_ORGANIZATIOIN_ID: 'SET_ORGANIZATIOIN_ID',
|
||||
SET_TENANT_ID: 'SET_TENANT_ID',
|
||||
SET_USER_ID: 'SET_USER_ID',
|
||||
SET_LOCALE: 'SET_LOCALE',
|
||||
};
|
||||
Reference in New Issue
Block a user