Skip to content

Commit

Permalink
feat: set default currency at organization level
Browse files Browse the repository at this point in the history
  • Loading branch information
ansmonjol committed Nov 6, 2023
1 parent 0e9377b commit 42576cf
Show file tree
Hide file tree
Showing 15 changed files with 340 additions and 22 deletions.
5 changes: 5 additions & 0 deletions ditto/base.json
Original file line number Diff line number Diff line change
Expand Up @@ -1589,6 +1589,11 @@
"text_65269cd46e7ec037a6823fd6": "There are no voided invoices",
"text_65269cd46e7ec037a6823fda": "You can void an invoice to mark it as non due. All voided invoices will be listed here",
"text_65269cd46e7ec037a6823fd8": "This voided invoice cannot be found",
"text_6543ca0fdebf76a18e159294": "Edit default currency",
"text_6543ca0fdebf76a18e159298": "This setting establishes a default currency for all object creations and for displaying the dashboards page.",
"text_6543ca0fdebf76a18e15929c": "Default currency",
"text_6543ca0fdebf76a18e1592ee": "All objects will be created in {{currency}}, and the dashboards will be displayed in {{currency}} as well. \nNeed flexibility? Define the currency of the object within it to override the one mentioned above.",
"text_6543ca0fdebf76a18e159303": "Default currency successfully edited",
"text_637f813d31381b1ed90ab315": "API Token",
"text_637f813d31381b1ed90ab322": "Copy key",
"text_637f813d31381b1ed90ab30e": "This API secret key is used to connect Stripe to Lago, edit it to make a new connection",
Expand Down
3 changes: 3 additions & 0 deletions ditto/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -310,5 +310,8 @@ sources:
fileName: 👍 [Ready for dev] - Invoices - Void invoices
- name: 👍 [Ready for dev] - Settings - Add redirect url to PSP
id: 65367cb378995a8fbb5e15f5
fileName: 👍 [Ready for dev] - Settings - Add redirect url to PSP
- name: 👍 [Ready for dev] - Dashboards - Add financial reporting to Lago
id: 6543ca0b70910093c87cd539
format: flat
variants: true
3 changes: 3 additions & 0 deletions ditto/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,9 @@ module.exports = {
"project_637f813a9ec65c29fc3ceef3": {
"base": require('./-ready-for-dev---customers---invoice-grace-period__base.json')
},
"project_6543ca0b70910093c87cd539": {
"base": require('./-ready-for-dev---dashboards---add-financial-reporting-to-lago__base.json')
},
"project_65269b3f720470569cb17228": {
"base": require('./-ready-for-dev---invoices---void-invoices__base.json')
},
Expand Down
155 changes: 155 additions & 0 deletions src/components/settings/EditDefaultCurrencyDialog.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,155 @@
import { gql } from '@apollo/client'
import { useFormik } from 'formik'
import { forwardRef, useImperativeHandle, useRef, useState } from 'react'
import styled from 'styled-components'
import { object, string } from 'yup'

import { Button, Dialog, DialogRef } from '~/components/designSystem'
import { ComboBoxField } from '~/components/form'
import { addToast } from '~/core/apolloClient'
import {
CurrencyEnum,
EditOrganizationDefaultCurrencyForDialogFragment,
UpdateOrganizationInput,
useUpdateOrganizationDefaultCurrencyMutation,
} from '~/generated/graphql'
import { useInternationalization } from '~/hooks/core/useInternationalization'
import { theme } from '~/styles'

gql`
fragment EditOrganizationDefaultCurrencyForDialog on Organization {
id
defaultCurrency
}
mutation updateOrganizationDefaultCurrency($input: UpdateOrganizationInput!) {
updateOrganization(input: $input) {
id
...EditOrganizationDefaultCurrencyForDialog
}
}
`

export interface EditDefaultCurrencyDialogRef {
openDialog: (localData: EditDefaultCurrencyDialogImperativeProps) => unknown
closeDialog: () => unknown
}

type EditDefaultCurrencyDialogImperativeProps = {
organization?: EditOrganizationDefaultCurrencyForDialogFragment | null
}

export const EditDefaultCurrencyDialog = forwardRef<EditDefaultCurrencyDialogRef>((_, ref) => {
const { translate } = useInternationalization()
const dialogRef = useRef<DialogRef>(null)
const [localData, setLocalData] = useState<EditDefaultCurrencyDialogImperativeProps | null>(null)
const [updateOrganization] = useUpdateOrganizationDefaultCurrencyMutation({
onCompleted(res) {
if (res?.updateOrganization) {
addToast({
severity: 'success',
translateKey: 'text_6543ca0fdebf76a18e159303',
})
}
},
})

const formikProps = useFormik<Pick<UpdateOrganizationInput, 'defaultCurrency'>>({
initialValues: {
defaultCurrency: localData?.organization?.defaultCurrency || CurrencyEnum.Usd,
},
validationSchema: object().shape({
defaultCurrency: string()
.test({
test: function (defaultCurrency) {
return Object.values(CurrencyEnum).includes(defaultCurrency as CurrencyEnum)
},
})
.required(''),
}),
validateOnMount: true,
enableReinitialize: true,
onSubmit: async (values) => {
await updateOrganization({
variables: {
input: values,
},
})
},
})

useImperativeHandle(ref, () => ({
openDialog: (data) => {
setLocalData(data)
dialogRef.current?.openDialog()
},
closeDialog: () => {
dialogRef.current?.closeDialog()
},
}))

return (
<Dialog
ref={dialogRef}
title={translate('text_6543ca0fdebf76a18e159294')}
description={translate('text_6543ca0fdebf76a18e159298')}
onClickAway={() => {
formikProps.resetForm()
}}
actions={({ closeDialog }) => (
<>
<Button
variant="quaternary"
onClick={() => {
closeDialog()
formikProps.resetForm()
}}
>
{translate('text_62bb10ad2a10bd182d002031')}
</Button>
<Button
variant="primary"
disabled={!formikProps.isValid || !formikProps.dirty}
onClick={async () => {
await formikProps.submitForm()
closeDialog()
formikProps.resetForm()
setLocalData(null)
}}
>
{translate('text_6543ca0fdebf76a18e159294')}
</Button>
</>
)}
>
<ContentWrapper>
<ComboBoxField
disableClearable
name="defaultCurrency"
label={translate('text_6543ca0fdebf76a18e15929c')}
data={Object.values(CurrencyEnum).map((currencyType) => ({
value: currencyType,
}))}
PopperProps={{ displayInDialog: true }}
formikProps={formikProps}
/>
</ContentWrapper>
</Dialog>
)
})

const ContentWrapper = styled.div`
display: flex;
gap: ${theme.spacing(3)};
margin-bottom: ${theme.spacing(8)};
> * {
flex: 1;
}
${theme.breakpoints.down('md')} {
flex-direction: column;
}
`

EditDefaultCurrencyDialog.displayName = 'forwardRef'
8 changes: 6 additions & 2 deletions src/components/wallets/AddWalletToCustomerDialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import {
useCreateCustomerWalletMutation,
} from '~/generated/graphql'
import { useInternationalization } from '~/hooks/core/useInternationalization'
import { useOrganizationInfos } from '~/hooks/useOrganizationInfos'
import { theme } from '~/styles'

gql`
Expand Down Expand Up @@ -56,8 +57,11 @@ interface AddWalletToCustomerDialogProps {
export const AddWalletToCustomerDialog = forwardRef<DialogRef, AddWalletToCustomerDialogProps>(
({ customerId, userCurrency }: AddWalletToCustomerDialogProps, ref) => {
const { translate } = useInternationalization()
const { organization } = useOrganizationInfos()
const [currencyError, setCurrencyError] = useState(false)
const currencyPrecision = getCurrencyPrecision(userCurrency || CurrencyEnum.Usd)
const currencyPrecision = getCurrencyPrecision(
userCurrency || organization?.defaultCurrency || CurrencyEnum.Usd
)
const [createWallet] = useCreateCustomerWalletMutation({
context: {
silentErrorCodes: [LagoApiError.UnprocessableEntity],
Expand Down Expand Up @@ -115,7 +119,7 @@ export const AddWalletToCustomerDialog = forwardRef<DialogRef, AddWalletToCustom
grantedCredits: '',
name: '',
paidCredits: '',
currency: userCurrency || CurrencyEnum.Usd,
currency: userCurrency || organization?.defaultCurrency || CurrencyEnum.Usd,
rateAmount: `1${
currencyPrecision === 3 ? '.000' : currencyPrecision === 4 ? '.0000' : '.00'
}`,
Expand Down
8 changes: 4 additions & 4 deletions src/core/timezone/__tests__/config.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,10 @@ describe('Timezone fongis', () => {
offset: '+9:00',
offsetInMinute: 540,
})
expect(TimeZonesConfig['TZ_AMERICA_LOS_ANGELES']).toStrictEqual({
name: 'America/Los_Angeles',
offset: '-7:00',
offsetInMinute: -420,
expect(TimeZonesConfig['TZ_AMERICA_ARGENTINA_BUENOS_AIRES']).toStrictEqual({
name: 'America/Argentina/Buenos_Aires',
offset: '-3:00',
offsetInMinute: -180,
})
expect(TimeZonesConfig['TZ_UTC']).toStrictEqual({
name: 'UTC',
Expand Down
Loading

0 comments on commit 42576cf

Please sign in to comment.