mirror of
https://github.com/bigcapitalhq/bigcapital.git
synced 2026-02-19 22:30:31 +00:00
feat: organization setup.
This commit is contained in:
@@ -5,10 +5,10 @@ export const getSetupWizardSteps = () => [
|
|||||||
label: intl.get('setup.plan.plans'),
|
label: intl.get('setup.plan.plans'),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: intl.get('setup.plan.initializing'),
|
label: intl.get('setup.plan.getting_started'),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: intl.get('setup.plan.getting_started'),
|
label: intl.get('setup.plan.initializing'),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: intl.get('setup.plan.congrats'),
|
label: intl.get('setup.plan.congrats'),
|
||||||
|
|||||||
@@ -2,37 +2,30 @@ import { connect } from 'react-redux';
|
|||||||
import {
|
import {
|
||||||
getOrganizationByIdFactory,
|
getOrganizationByIdFactory,
|
||||||
isOrganizationReadyFactory,
|
isOrganizationReadyFactory,
|
||||||
isOrganizationSeededFactory,
|
|
||||||
isOrganizationBuiltFactory,
|
isOrganizationBuiltFactory,
|
||||||
isOrganizationSeedingFactory,
|
|
||||||
isOrganizationInitializingFactory,
|
|
||||||
isOrganizationSubscribedFactory,
|
isOrganizationSubscribedFactory,
|
||||||
isOrganizationCongratsFactory,
|
isOrganizationCongratsFactory,
|
||||||
|
isOrganizationBuildRunningFactory
|
||||||
} from 'store/organizations/organizations.selectors';
|
} from 'store/organizations/organizations.selectors';
|
||||||
|
|
||||||
export default (mapState) => {
|
export default (mapState) => {
|
||||||
const getOrganizationById = getOrganizationByIdFactory();
|
const getOrganizationById = getOrganizationByIdFactory();
|
||||||
const isOrganizationReady = isOrganizationReadyFactory();
|
const isOrganizationReady = isOrganizationReadyFactory();
|
||||||
|
|
||||||
const isOrganizationSeeded = isOrganizationSeededFactory();
|
|
||||||
const isOrganizationBuilt = isOrganizationBuiltFactory();
|
const isOrganizationBuilt = isOrganizationBuiltFactory();
|
||||||
|
|
||||||
const isOrganizationInitializing = isOrganizationInitializingFactory();
|
|
||||||
const isOrganizationSeeding = isOrganizationSeedingFactory();
|
|
||||||
|
|
||||||
const isOrganizationSubscribed = isOrganizationSubscribedFactory();
|
const isOrganizationSubscribed = isOrganizationSubscribedFactory();
|
||||||
const isOrganizationCongrats = isOrganizationCongratsFactory();
|
const isOrganizationCongrats = isOrganizationCongratsFactory();
|
||||||
|
const isOrganizationBuildRunning = isOrganizationBuildRunningFactory();
|
||||||
|
|
||||||
const mapStateToProps = (state, props) => {
|
const mapStateToProps = (state, props) => {
|
||||||
const mapped = {
|
const mapped = {
|
||||||
organization: getOrganizationById(state, props),
|
organization: getOrganizationById(state, props),
|
||||||
isOrganizationReady: isOrganizationReady(state, props),
|
isOrganizationReady: isOrganizationReady(state, props),
|
||||||
isOrganizationSeeded: isOrganizationSeeded(state, props),
|
|
||||||
isOrganizationInitialized: isOrganizationBuilt(state, props),
|
isOrganizationInitialized: isOrganizationBuilt(state, props),
|
||||||
isOrganizationSeeding: isOrganizationInitializing(state, props),
|
|
||||||
isOrganizationInitializing: isOrganizationSeeding(state, props),
|
|
||||||
isOrganizationSubscribed: isOrganizationSubscribed(state, props),
|
isOrganizationSubscribed: isOrganizationSubscribed(state, props),
|
||||||
isOrganizationSetupCompleted: isOrganizationCongrats(state, props),
|
isOrganizationSetupCompleted: isOrganizationCongrats(state, props),
|
||||||
|
isOrganizationBuildRunning: isOrganizationBuildRunning(state, props)
|
||||||
};
|
};
|
||||||
return (mapState) ? mapState(mapped, state, props) : mapped;
|
return (mapState) ? mapState(mapped, state, props) : mapped;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,62 +1,108 @@
|
|||||||
import React, { useEffect } from 'react';
|
import React from 'react';
|
||||||
import { ProgressBar, Intent } from '@blueprintjs/core';
|
import { ProgressBar, Intent } from '@blueprintjs/core';
|
||||||
import { useBuildTenant } from 'hooks/query';
|
import * as R from 'ramda';
|
||||||
|
|
||||||
|
import { useJob, useCurrentOrganization } from 'hooks/query';
|
||||||
import { FormattedMessage as T } from 'components';
|
import { FormattedMessage as T } from 'components';
|
||||||
|
|
||||||
|
import withOrganizationActions from 'containers/Organization/withOrganizationActions';
|
||||||
|
import withCurrentOrganization from 'containers/Organization/withCurrentOrganization';
|
||||||
|
import withOrganization from '../Organization/withOrganization';
|
||||||
|
|
||||||
import 'style/pages/Setup/Initializing.scss';
|
import 'style/pages/Setup/Initializing.scss';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Setup initializing step form.
|
* Setup initializing step form.
|
||||||
*/
|
*/
|
||||||
export default function SetupInitializingForm() {
|
function SetupInitializingForm({
|
||||||
|
setOrganizationSetupCompleted,
|
||||||
|
organization,
|
||||||
|
}) {
|
||||||
|
const { refetch, isSuccess } = useCurrentOrganization({ enabled: false });
|
||||||
|
|
||||||
|
const [isJobDone, setIsJobDone] = React.useState(false);
|
||||||
|
|
||||||
const {
|
const {
|
||||||
mutateAsync: buildTenantMutate,
|
data: { running, queued, failed, completed },
|
||||||
isLoading,
|
} = useJob(organization?.build_job_id, {
|
||||||
isError,
|
refetchInterval: 2000,
|
||||||
} = useBuildTenant();
|
enabled: !!organization?.build_job_id,
|
||||||
|
});
|
||||||
|
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
buildTenantMutate();
|
if (completed) {
|
||||||
}, [buildTenantMutate]);
|
refetch();
|
||||||
|
setIsJobDone(true);
|
||||||
|
}
|
||||||
|
}, [refetch, completed, setOrganizationSetupCompleted]);
|
||||||
|
|
||||||
|
React.useEffect(() => {
|
||||||
|
if (isSuccess && isJobDone) {
|
||||||
|
setOrganizationSetupCompleted(true);
|
||||||
|
setIsJobDone(false);
|
||||||
|
}
|
||||||
|
}, [setOrganizationSetupCompleted, isJobDone, isSuccess]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div class="setup-initializing-form">
|
<div class="setup-initializing-form">
|
||||||
{isLoading && <ProgressBar intent={Intent.PRIMARY} value={null} />}
|
<ProgressBar intent={Intent.PRIMARY} value={null} />
|
||||||
|
|
||||||
<div className={'setup-initializing-form__title'}>
|
<div className={'setup-initializing-form__title'}>
|
||||||
{isLoading ? (
|
{failed ? (
|
||||||
<>
|
<SetupInitializingFailed />
|
||||||
<h1>
|
) : running || queued ? (
|
||||||
<T id={'setup.initializing.title'} />
|
<SetupInitializingRunning />
|
||||||
</h1>
|
) : completed ? (
|
||||||
<p className={'paragraph'}>
|
<SetupInitializingCompleted />
|
||||||
<T id={'setup.initializing.description'} />
|
) : null}
|
||||||
</p>
|
|
||||||
</>
|
|
||||||
) : isError ? (
|
|
||||||
<>
|
|
||||||
<h1>
|
|
||||||
<T id={'setup.initializing.something_went_wrong'} />
|
|
||||||
</h1>
|
|
||||||
<p class="paragraph">
|
|
||||||
<T id={'setup.initializing.please_refresh_the_page'} />
|
|
||||||
</p>
|
|
||||||
</>
|
|
||||||
) : (
|
|
||||||
<>
|
|
||||||
<h1>
|
|
||||||
<T id={'setup.initializing.waiting_to_redirect'} />
|
|
||||||
</h1>
|
|
||||||
<p class="paragraph">
|
|
||||||
<T
|
|
||||||
id={
|
|
||||||
'setup.initializing.refresh_the_page_if_redirect_not_worked'
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
</p>
|
|
||||||
</>
|
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export default R.compose(
|
||||||
|
withOrganizationActions,
|
||||||
|
withCurrentOrganization(({ organizationTenantId }) => ({
|
||||||
|
organizationId: organizationTenantId,
|
||||||
|
})),
|
||||||
|
withOrganization(({ organization }) => ({ organization })),
|
||||||
|
)(SetupInitializingForm);
|
||||||
|
|
||||||
|
function SetupInitializingFailed() {
|
||||||
|
return (
|
||||||
|
<div class="failed">
|
||||||
|
<h1>
|
||||||
|
<T id={'setup.initializing.something_went_wrong'} />
|
||||||
|
</h1>
|
||||||
|
<p class="paragraph">
|
||||||
|
<T id={'setup.initializing.please_refresh_the_page'} />
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function SetupInitializingRunning() {
|
||||||
|
return (
|
||||||
|
<div class="running">
|
||||||
|
<h1>
|
||||||
|
<T id={'setup.initializing.title'} />
|
||||||
|
</h1>
|
||||||
|
<p className={'paragraph'}>
|
||||||
|
<T id={'setup.initializing.description'} />
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function SetupInitializingCompleted() {
|
||||||
|
return (
|
||||||
|
<div class="completed">
|
||||||
|
<h1>
|
||||||
|
<T id={'setup.initializing.waiting_to_redirect'} />
|
||||||
|
</h1>
|
||||||
|
<p class="paragraph">
|
||||||
|
<T id={'setup.initializing.refresh_the_page_if_redirect_not_worked'} />
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|||||||
@@ -11,5 +11,5 @@ export const getSetupOrganizationValidation = () =>
|
|||||||
baseCurrency: Yup.string().required().label(intl.get('base_currency_')),
|
baseCurrency: Yup.string().required().label(intl.get('base_currency_')),
|
||||||
language: Yup.string().required().label(intl.get('language')),
|
language: Yup.string().required().label(intl.get('language')),
|
||||||
fiscalYear: Yup.string().required().label(intl.get('fiscal_year_')),
|
fiscalYear: Yup.string().required().label(intl.get('fiscal_year_')),
|
||||||
timeZone: Yup.string().required().label(intl.get('time_zone_')),
|
timezone: Yup.string().required().label(intl.get('time_zone_')),
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -195,7 +195,7 @@ export default function SetupOrganizationForm({ isSubmitting, values }) {
|
|||||||
</FastField>
|
</FastField>
|
||||||
|
|
||||||
{/* ---------- Time zone ---------- */}
|
{/* ---------- Time zone ---------- */}
|
||||||
<FastField name={'timeZone'}>
|
<FastField name={'timezone'}>
|
||||||
{({
|
{({
|
||||||
form: { setFieldValue },
|
form: { setFieldValue },
|
||||||
field: { value },
|
field: { value },
|
||||||
@@ -209,12 +209,12 @@ export default function SetupOrganizationForm({ isSubmitting, values }) {
|
|||||||
Classes.FILL,
|
Classes.FILL,
|
||||||
)}
|
)}
|
||||||
intent={inputIntent({ error, touched })}
|
intent={inputIntent({ error, touched })}
|
||||||
helperText={<ErrorMessage name={'timeZone'} />}
|
helperText={<ErrorMessage name={'timezone'} />}
|
||||||
>
|
>
|
||||||
<TimezonePicker
|
<TimezonePicker
|
||||||
value={value}
|
value={value}
|
||||||
onChange={(item) => {
|
onChange={(item) => {
|
||||||
setFieldValue('timeZone', item);
|
setFieldValue('timezone', item);
|
||||||
}}
|
}}
|
||||||
valueDisplayFormat="composite"
|
valueDisplayFormat="composite"
|
||||||
showLocalTimezone={true}
|
showLocalTimezone={true}
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ import { Formik } from 'formik';
|
|||||||
import moment from 'moment';
|
import moment from 'moment';
|
||||||
import { FormattedMessage as T } from 'components';
|
import { FormattedMessage as T } from 'components';
|
||||||
|
|
||||||
|
|
||||||
import 'style/pages/Setup/Organization.scss';
|
import 'style/pages/Setup/Organization.scss';
|
||||||
|
|
||||||
import SetupOrganizationForm from './SetupOrganizationForm';
|
import SetupOrganizationForm from './SetupOrganizationForm';
|
||||||
@@ -15,7 +14,6 @@ import withOrganizationActions from 'containers/Organization/withOrganizationAct
|
|||||||
import { compose, transfromToSnakeCase } from 'utils';
|
import { compose, transfromToSnakeCase } from 'utils';
|
||||||
import { getSetupOrganizationValidation } from './SetupOrganization.schema';
|
import { getSetupOrganizationValidation } from './SetupOrganization.schema';
|
||||||
|
|
||||||
|
|
||||||
// Initial values.
|
// Initial values.
|
||||||
const defaultValues = {
|
const defaultValues = {
|
||||||
organization_name: '',
|
organization_name: '',
|
||||||
@@ -23,7 +21,7 @@ const defaultValues = {
|
|||||||
baseCurrency: '',
|
baseCurrency: '',
|
||||||
language: 'en',
|
language: 'en',
|
||||||
fiscalYear: '',
|
fiscalYear: '',
|
||||||
timeZone: '',
|
timezone: '',
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -43,9 +41,6 @@ function SetupOrganizationPage({ wizard, setOrganizationSetupCompleted }) {
|
|||||||
// Handle the form submit.
|
// Handle the form submit.
|
||||||
const handleSubmit = (values, { setSubmitting, setErrors }) => {
|
const handleSubmit = (values, { setSubmitting, setErrors }) => {
|
||||||
organizationSetupMutate({ ...transfromToSnakeCase(values) })
|
organizationSetupMutate({ ...transfromToSnakeCase(values) })
|
||||||
.then(() => {
|
|
||||||
return setOrganizationSetupCompleted(true);
|
|
||||||
})
|
|
||||||
.then((response) => {
|
.then((response) => {
|
||||||
setSubmitting(false);
|
setSubmitting(false);
|
||||||
wizard.next();
|
wizard.next();
|
||||||
|
|||||||
@@ -47,11 +47,13 @@ export default compose(
|
|||||||
isOrganizationInitialized,
|
isOrganizationInitialized,
|
||||||
isOrganizationSeeded,
|
isOrganizationSeeded,
|
||||||
isOrganizationSetupCompleted,
|
isOrganizationSetupCompleted,
|
||||||
|
isOrganizationBuildRunning,
|
||||||
}) => ({
|
}) => ({
|
||||||
organization,
|
organization,
|
||||||
isOrganizationInitialized,
|
isOrganizationInitialized,
|
||||||
isOrganizationSeeded,
|
isOrganizationSeeded,
|
||||||
isOrganizationSetupCompleted,
|
isOrganizationSetupCompleted,
|
||||||
|
isOrganizationBuildRunning,
|
||||||
}),
|
}),
|
||||||
),
|
),
|
||||||
withSubscriptions(
|
withSubscriptions(
|
||||||
|
|||||||
@@ -19,8 +19,8 @@ export default function SetupWizardContent({ setupStepIndex, setupStepId }) {
|
|||||||
<div class="setup-page-form">
|
<div class="setup-page-form">
|
||||||
<SetupSteps step={{ id: setupStepId }}>
|
<SetupSteps step={{ id: setupStepId }}>
|
||||||
<SetupSubscription id="subscription" />
|
<SetupSubscription id="subscription" />
|
||||||
<SetupInitializingForm id={'initializing'} />
|
|
||||||
<SetupOrganizationPage id="organization" />
|
<SetupOrganizationPage id="organization" />
|
||||||
|
<SetupInitializingForm id={'initializing'} />
|
||||||
<SetupCongratsPage id="congrats" />
|
<SetupCongratsPage id="congrats" />
|
||||||
</SetupSteps>
|
</SetupSteps>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -26,3 +26,4 @@ export * from './organization';
|
|||||||
export * from './landedCost';
|
export * from './landedCost';
|
||||||
export * from './UniversalSearch/UniversalSearch';
|
export * from './UniversalSearch/UniversalSearch';
|
||||||
export * from './GenericResource';
|
export * from './GenericResource';
|
||||||
|
export * from './jobs';
|
||||||
|
|||||||
16
client/src/hooks/query/jobs.js
Normal file
16
client/src/hooks/query/jobs.js
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
import { useRequestQuery } from '../useQueryRequest';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve the job metadata.
|
||||||
|
*/
|
||||||
|
export function useJob(jobId, props = {}) {
|
||||||
|
return useRequestQuery(
|
||||||
|
['JOB', jobId],
|
||||||
|
{ method: 'get', url: `jobs/${jobId}` },
|
||||||
|
{
|
||||||
|
select: (res) => res.data.job,
|
||||||
|
defaultData: {},
|
||||||
|
...props,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -35,7 +35,7 @@ export function useCurrentOrganization(props) {
|
|||||||
|
|
||||||
return useRequestQuery(
|
return useRequestQuery(
|
||||||
[t.ORGANIZATION_CURRENT],
|
[t.ORGANIZATION_CURRENT],
|
||||||
{ method: 'get', url: `organization/current` },
|
{ method: 'get', url: `organization` },
|
||||||
{
|
{
|
||||||
select: (res) => res.data.organization,
|
select: (res) => res.data.organization,
|
||||||
defaultData: {},
|
defaultData: {},
|
||||||
@@ -55,37 +55,6 @@ export function useCurrentOrganization(props) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Builds the current tenant.
|
|
||||||
*/
|
|
||||||
export function useBuildTenant(props) {
|
|
||||||
const apiRequest = useApiRequest();
|
|
||||||
const queryClient = useQueryClient();
|
|
||||||
|
|
||||||
return useMutation((values) => apiRequest.post('organization/build'), {
|
|
||||||
onSuccess: (res, values) => {
|
|
||||||
queryClient.invalidateQueries(t.ORGANIZATION_CURRENT);
|
|
||||||
queryClient.invalidateQueries(t.ORGANIZATIONS);
|
|
||||||
},
|
|
||||||
...props,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Seeds the current tenant
|
|
||||||
*/
|
|
||||||
export function useSeedTenant() {
|
|
||||||
const apiRequest = useApiRequest();
|
|
||||||
const queryClient = useQueryClient();
|
|
||||||
|
|
||||||
return useMutation((values) => apiRequest.post('organization/seed'), {
|
|
||||||
onSuccess: (res) => {
|
|
||||||
queryClient.invalidateQueries(t.ORGANIZATION_CURRENT);
|
|
||||||
queryClient.invalidateQueries(t.ORGANIZATIONS);
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Organization setup.
|
* Organization setup.
|
||||||
*/
|
*/
|
||||||
@@ -94,7 +63,7 @@ export function useOrganizationSetup() {
|
|||||||
const queryClient = useQueryClient();
|
const queryClient = useQueryClient();
|
||||||
|
|
||||||
return useMutation(
|
return useMutation(
|
||||||
(values) => apiRequest.post(`setup/organization`, values),
|
(values) => apiRequest.post(`organization/build`, values),
|
||||||
{
|
{
|
||||||
onSuccess: (res) => {
|
onSuccess: (res) => {
|
||||||
queryClient.invalidateQueries(t.ORGANIZATION_CURRENT);
|
queryClient.invalidateQueries(t.ORGANIZATION_CURRENT);
|
||||||
|
|||||||
@@ -8,66 +8,34 @@ export const setOrganizations = (organizations) => {
|
|||||||
organizations,
|
organizations,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
}
|
};
|
||||||
|
|
||||||
|
export const fetchOrganizations = () => (dispatch) =>
|
||||||
|
new Promise((resolve, reject) => {
|
||||||
|
ApiService.get('organization/all')
|
||||||
|
.then((response) => {
|
||||||
|
dispatch({
|
||||||
|
type: t.ORGANIZATIONS_LIST_SET,
|
||||||
|
payload: {
|
||||||
|
organizations: response.data.organizations,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
resolve(response);
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
reject(error);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
export const setOrganizationSetupCompleted =
|
||||||
|
(congrats) => (dispatch, getState) => {
|
||||||
|
const organizationId = getState().authentication.organizationId;
|
||||||
|
|
||||||
export const fetchOrganizations = () => (dispatch) => new Promise((resolve, reject) => {
|
|
||||||
ApiService.get('organization/all').then((response) => {
|
|
||||||
dispatch({
|
dispatch({
|
||||||
type: t.ORGANIZATIONS_LIST_SET,
|
type: t.SET_ORGANIZATION_CONGRATS,
|
||||||
payload: {
|
payload: {
|
||||||
organizations: response.data.organizations,
|
organizationId,
|
||||||
|
congrats,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
resolve(response)
|
};
|
||||||
}).catch(error => { reject(error); });
|
|
||||||
});
|
|
||||||
|
|
||||||
export const buildTenant = () => (dispatch, getState) => new Promise((resolve, reject) => {
|
|
||||||
const organizationId = getState().authentication.organizationId;
|
|
||||||
|
|
||||||
dispatch({
|
|
||||||
type: t.SET_ORGANIZATION_INITIALIZING,
|
|
||||||
payload: { organizationId }
|
|
||||||
});
|
|
||||||
ApiService.post(`organization/build`).then((response) => {
|
|
||||||
resolve(response);
|
|
||||||
dispatch({
|
|
||||||
type: t.SET_ORGANIZATION_INITIALIZED,
|
|
||||||
payload: { organizationId }
|
|
||||||
});
|
|
||||||
})
|
|
||||||
.catch((error) => {
|
|
||||||
reject(error.response.data.errors || []);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
export const seedTenant = () => (dispatch, getState) => new Promise((resolve, reject) => {
|
|
||||||
const organizationId = getState().authentication.organizationId;
|
|
||||||
|
|
||||||
dispatch({
|
|
||||||
type: t.SET_ORGANIZATION_SEEDING,
|
|
||||||
payload: { organizationId }
|
|
||||||
});
|
|
||||||
ApiService.post(`organization/seed/`).then((response) => {
|
|
||||||
dispatch({
|
|
||||||
type: t.SET_ORGANIZATION_SEEDED,
|
|
||||||
payload: { organizationId }
|
|
||||||
});
|
|
||||||
resolve(response);
|
|
||||||
})
|
|
||||||
.catch((error) => {
|
|
||||||
reject(error.response.data.errors || []);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
export const setOrganizationSetupCompleted = (congrats) => (dispatch, getState) => {
|
|
||||||
const organizationId = getState().authentication.organizationId;
|
|
||||||
|
|
||||||
dispatch({
|
|
||||||
type: t.SET_ORGANIZATION_CONGRATS,
|
|
||||||
payload: {
|
|
||||||
organizationId,
|
|
||||||
congrats
|
|
||||||
},
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|||||||
@@ -24,45 +24,6 @@ const reducer = createReducer(initialState, {
|
|||||||
state.byOrganizationId = _dataByOrganizationId;
|
state.byOrganizationId = _dataByOrganizationId;
|
||||||
},
|
},
|
||||||
|
|
||||||
[t.SET_ORGANIZATION_SEEDING]: (state, action) => {
|
|
||||||
const { organizationId } = action.payload;
|
|
||||||
|
|
||||||
state.data[organizationId] = {
|
|
||||||
...(state.data[organizationId] || {}),
|
|
||||||
is_seeding: true,
|
|
||||||
};
|
|
||||||
},
|
|
||||||
|
|
||||||
[t.SET_ORGANIZATION_SEEDED]: (state, action) => {
|
|
||||||
const { organizationId } = action.payload;
|
|
||||||
|
|
||||||
state.data[organizationId] = {
|
|
||||||
...(state.data[organizationId] || {}),
|
|
||||||
is_seeding: false,
|
|
||||||
seeded_at: new Date().toISOString(),
|
|
||||||
is_ready: true,
|
|
||||||
};
|
|
||||||
},
|
|
||||||
|
|
||||||
[t.SET_ORGANIZATION_INITIALIZING]: (state, action) => {
|
|
||||||
const { organizationId } = action.payload;
|
|
||||||
|
|
||||||
state.data[organizationId] = {
|
|
||||||
...(state.data[organizationId] || {}),
|
|
||||||
is_initializing: true,
|
|
||||||
};
|
|
||||||
},
|
|
||||||
|
|
||||||
[t.SET_ORGANIZATION_INITIALIZED]: (state, action) => {
|
|
||||||
const { organizationId } = action.payload;
|
|
||||||
|
|
||||||
state.data[organizationId] = {
|
|
||||||
...(state.data[organizationId] || {}),
|
|
||||||
is_initializing: false,
|
|
||||||
initialized_at: new Date().toISOString(),
|
|
||||||
};
|
|
||||||
},
|
|
||||||
|
|
||||||
[t.SET_ORGANIZATION_CONGRATS]: (state, action) => {
|
[t.SET_ORGANIZATION_CONGRATS]: (state, action) => {
|
||||||
const { organizationId, congrats } = action.payload;
|
const { organizationId, congrats } = action.payload;
|
||||||
|
|
||||||
|
|||||||
@@ -21,20 +21,6 @@ export const isOrganizationBuiltFactory = () => createSelector(
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
export const isOrganizationInitializingFactory = () => createSelector(
|
|
||||||
organizationSelector,
|
|
||||||
(organization) => {
|
|
||||||
return organization?.is_initializing;
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
export const isOrganizationSeedingFactory = () => createSelector(
|
|
||||||
organizationSelector,
|
|
||||||
(organization) => {
|
|
||||||
return organization?.is_seeding;
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
export const isOrganizationReadyFactory = () => createSelector(
|
export const isOrganizationReadyFactory = () => createSelector(
|
||||||
organizationSelector,
|
organizationSelector,
|
||||||
(organization) => {
|
(organization) => {
|
||||||
@@ -55,3 +41,10 @@ export const isOrganizationCongratsFactory = () => createSelector(
|
|||||||
return !!organization?.is_congrats;
|
return !!organization?.is_congrats;
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
export const isOrganizationBuildRunningFactory = () => createSelector(
|
||||||
|
organizationSelector,
|
||||||
|
(organization) => {
|
||||||
|
return !!organization?.is_build_running;
|
||||||
|
}
|
||||||
|
)
|
||||||
@@ -1,12 +1,5 @@
|
|||||||
|
|
||||||
export default {
|
export default {
|
||||||
ORGANIZATIONS_LIST_SET: 'ORGANIZATIONS_LIST_SET',
|
ORGANIZATIONS_LIST_SET: 'ORGANIZATIONS_LIST_SET',
|
||||||
|
|
||||||
SET_ORGANIZATION_SEEDING: 'SET_ORGANIZATION_SEEDING',
|
|
||||||
SET_ORGANIZATION_SEEDED: 'SET_ORGANIZATION_SEEDED',
|
|
||||||
|
|
||||||
SET_ORGANIZATION_INITIALIZED: 'SET_ORGANIZATION_INITIALIZED',
|
|
||||||
SET_ORGANIZATION_INITIALIZING: 'SET_ORGANIZATION_INITIALIZING',
|
|
||||||
|
|
||||||
SET_ORGANIZATION_CONGRATS: 'SET_ORGANIZATION_CONGRATS'
|
SET_ORGANIZATION_CONGRATS: 'SET_ORGANIZATION_CONGRATS'
|
||||||
};
|
};
|
||||||
@@ -5,28 +5,27 @@ export default (mapState) => {
|
|||||||
const {
|
const {
|
||||||
isOrganizationSetupCompleted,
|
isOrganizationSetupCompleted,
|
||||||
isOrganizationInitialized,
|
isOrganizationInitialized,
|
||||||
isOrganizationSeeded,
|
isSubscriptionActive,
|
||||||
isSubscriptionActive
|
isOrganizationBuildRunning
|
||||||
} = props;
|
} = props;
|
||||||
|
|
||||||
const condits = {
|
const condits = {
|
||||||
isCongratsStep: isOrganizationSetupCompleted,
|
isCongratsStep: isOrganizationSetupCompleted,
|
||||||
isSubscriptionStep: !isSubscriptionActive,
|
isSubscriptionStep: !isSubscriptionActive,
|
||||||
isInitializingStep: isSubscriptionActive && !isOrganizationInitialized,
|
isInitializingStep: isOrganizationBuildRunning,
|
||||||
isOrganizationStep: isOrganizationInitialized && !isOrganizationSeeded,
|
isOrganizationStep: !isOrganizationInitialized && !isOrganizationBuildRunning,
|
||||||
};
|
};
|
||||||
|
|
||||||
const scenarios = [
|
const scenarios = [
|
||||||
{ condition: condits.isCongratsStep, step: 'congrats' },
|
|
||||||
{ condition: condits.isSubscriptionStep, step: 'subscription' },
|
{ condition: condits.isSubscriptionStep, step: 'subscription' },
|
||||||
{ condition: condits.isInitializingStep, step: 'initializing' },
|
|
||||||
{ condition: condits.isOrganizationStep, step: 'organization' },
|
{ condition: condits.isOrganizationStep, step: 'organization' },
|
||||||
|
{ condition: condits.isInitializingStep, step: 'initializing' },
|
||||||
|
{ condition: condits.isCongratsStep, step: 'congrats' },
|
||||||
];
|
];
|
||||||
const setupStep = scenarios.find((scenario) => scenario.condition);
|
const setupStep = scenarios.find((scenario) => scenario.condition);
|
||||||
const mapped = {
|
const mapped = {
|
||||||
...condits,
|
...condits,
|
||||||
setupStepId: setupStep?.step,
|
setupStepId: setupStep?.step,
|
||||||
setupStepIndex: scenarios.indexOf(setupStep) ,
|
setupStepIndex: scenarios.indexOf(setupStep) + 1,
|
||||||
};
|
};
|
||||||
return mapState ? mapState(mapped, state, props) : mapped;
|
return mapState ? mapState(mapped, state, props) : mapped;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -59,7 +59,7 @@ export default class OrganizationController extends BaseController {
|
|||||||
check('organization_name').exists().trim(),
|
check('organization_name').exists().trim(),
|
||||||
check('base_currency').exists().isIn(BASE_CURRENCY),
|
check('base_currency').exists().isIn(BASE_CURRENCY),
|
||||||
check('timezone').exists(),
|
check('timezone').exists(),
|
||||||
check('fiscal_year').exists().isISO8601(),
|
check('fiscal_year').exists(),
|
||||||
check('industry').optional().isString(),
|
check('industry').optional().isString(),
|
||||||
check('date_format').optional().isIn(DATE_FORMATS),
|
check('date_format').optional().isIn(DATE_FORMATS),
|
||||||
];
|
];
|
||||||
|
|||||||
@@ -2,40 +2,40 @@ import Container from 'typedi';
|
|||||||
import TenancyService from 'services/Tenancy/TenancyService';
|
import TenancyService from 'services/Tenancy/TenancyService';
|
||||||
|
|
||||||
exports.up = (knex) => {
|
exports.up = (knex) => {
|
||||||
const tenancyService = Container.get(TenancyService);
|
// const tenancyService = Container.get(TenancyService);
|
||||||
const settings = tenancyService.settings(knex.userParams.tenantId);
|
// const settings = tenancyService.settings(knex.userParams.tenantId);
|
||||||
|
|
||||||
// Orgnization settings.
|
// // Orgnization settings.
|
||||||
settings.set({ group: 'organization', key: 'accounting_basis', value: 'accural' });
|
// settings.set({ group: 'organization', key: 'accounting_basis', value: 'accural' });
|
||||||
|
|
||||||
// Accounts settings.
|
// // Accounts settings.
|
||||||
settings.set({ group: 'accounts', key: 'account_code_unique', value: true });
|
// settings.set({ group: 'accounts', key: 'account_code_unique', value: true });
|
||||||
|
|
||||||
// Manual journals settings.
|
// // Manual journals settings.
|
||||||
settings.set({ group: 'manual_journals', key: 'next_number', value: '00001' });
|
// settings.set({ group: 'manual_journals', key: 'next_number', value: '00001' });
|
||||||
settings.set({ group: 'manual_journals', key: 'auto_increment', value: true });
|
// settings.set({ group: 'manual_journals', key: 'auto_increment', value: true });
|
||||||
|
|
||||||
// Sale invoices settings.
|
// // Sale invoices settings.
|
||||||
settings.set({ group: 'sales_invoices', key: 'next_number', value: '00001' });
|
// settings.set({ group: 'sales_invoices', key: 'next_number', value: '00001' });
|
||||||
settings.set({ group: 'sales_invoices', key: 'number_prefix', value: 'INV-' });
|
// settings.set({ group: 'sales_invoices', key: 'number_prefix', value: 'INV-' });
|
||||||
settings.set({ group: 'sales_invoices', key: 'auto_increment', value: true });
|
// settings.set({ group: 'sales_invoices', key: 'auto_increment', value: true });
|
||||||
|
|
||||||
// Sale receipts settings.
|
// // Sale receipts settings.
|
||||||
settings.set({ group: 'sales_receipts', key: 'next_number', value: '00001' });
|
// settings.set({ group: 'sales_receipts', key: 'next_number', value: '00001' });
|
||||||
settings.set({ group: 'sales_receipts', key: 'number_prefix', value: 'REC-' });
|
// settings.set({ group: 'sales_receipts', key: 'number_prefix', value: 'REC-' });
|
||||||
settings.set({ group: 'sales_receipts', key: 'auto_increment', value: true });
|
// settings.set({ group: 'sales_receipts', key: 'auto_increment', value: true });
|
||||||
|
|
||||||
// Sale estimates settings.
|
// // Sale estimates settings.
|
||||||
settings.set({ group: 'sales_estimates', key: 'next_number', value: '00001' });
|
// settings.set({ group: 'sales_estimates', key: 'next_number', value: '00001' });
|
||||||
settings.set({ group: 'sales_estimates', key: 'number_prefix', value: 'EST-' });
|
// settings.set({ group: 'sales_estimates', key: 'number_prefix', value: 'EST-' });
|
||||||
settings.set({ group: 'sales_estimates', key: 'auto_increment', value: true });
|
// settings.set({ group: 'sales_estimates', key: 'auto_increment', value: true });
|
||||||
|
|
||||||
// Payment receives settings.
|
// // Payment receives settings.
|
||||||
settings.set({ group: 'payment_receives', key: 'number_prefix', value: 'PAY-' });
|
// settings.set({ group: 'payment_receives', key: 'number_prefix', value: 'PAY-' });
|
||||||
settings.set({ group: 'payment_receives', key: 'next_number', value: '00001' });
|
// settings.set({ group: 'payment_receives', key: 'next_number', value: '00001' });
|
||||||
settings.set({ group: 'payment_receives', key: 'auto_increment', value: true });
|
// settings.set({ group: 'payment_receives', key: 'auto_increment', value: true });
|
||||||
|
|
||||||
return settings.save();
|
// return settings.save();
|
||||||
};
|
};
|
||||||
|
|
||||||
exports.down = (knex) => {};
|
exports.down = (knex) => {};
|
||||||
|
|||||||
Reference in New Issue
Block a user