Skip to content

Commit

Permalink
enhancement(ExpenseForm): use 'Gross amount' label if taxes (#11008)
Browse files Browse the repository at this point in the history
  • Loading branch information
Betree authored Feb 24, 2025
1 parent 8feefa4 commit d42b6d3
Show file tree
Hide file tree
Showing 8 changed files with 277 additions and 9 deletions.
1 change: 1 addition & 0 deletions components/expenses/ExpenseFormItems.js
Original file line number Diff line number Diff line change
Expand Up @@ -237,6 +237,7 @@ class ExpenseFormItems extends React.PureComponent {
ocrComparison={itemsOCRComparisons[attachment.id]}
hasCurrencyPicker={itemsHaveCurrencyPicker}
amountIsLocked={amountIsLocked}
isSubjectToTax={Boolean(taxType)}
/>
))}
{/** Do not display OCR warnings for OCR charges since date/amount can't be changed */}
Expand Down
9 changes: 8 additions & 1 deletion components/expenses/ExpenseItemForm.js
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,10 @@ const msg = defineMessages({
id: 'Fields.description',
defaultMessage: 'Description',
},
grossAmountLabel: {
id: 'bwZInO',
defaultMessage: 'Gross Amount',
},
amountLabel: {
id: 'Fields.amount',
defaultMessage: 'Amount',
Expand Down Expand Up @@ -333,6 +337,7 @@ const ExpenseItemForm = ({
ocrComparison,
hasCurrencyPicker,
amountIsLocked,
isSubjectToTax = false,
}) => {
const intl = useIntl();
const form = useFormikContext();
Expand Down Expand Up @@ -476,7 +481,7 @@ const ExpenseItemForm = ({
name={getFieldName('amountV2')}
error={getError('amountV2')}
htmlFor={`${getFieldName('amountV2')}-amount`}
label={formatMessage(msg.amountLabel)}
label={formatMessage(isSubjectToTax ? msg.grossAmountLabel : msg.amountLabel)}
required
labelFontSize="13px"
inputType="number"
Expand Down Expand Up @@ -616,6 +621,8 @@ ExpenseItemForm.propTypes = {
onUploadError: PropTypes.func.isRequired,
/** Is it an invoice */
isInvoice: PropTypes.bool,
/** Whether the item is subject to tax */
isSubjectToTax: PropTypes.bool,
/** the item data. TODO: Rename to "item" */
attachment: PropTypes.shape({
id: PropTypes.string,
Expand Down
16 changes: 13 additions & 3 deletions components/submit-expense/form/ExpenseItemsSection.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,11 @@ export const ExpenseItemsForm = memoWithGetFormProps(function ExpenseItemsForm(
// eslint-disable-next-line react/no-array-index-key
<div key={ei.key} id={ei.key} role="listitem" className="flex gap-4">
<div className="grow">
<ExpenseItemWrapper index={i} isAmountLocked={isAmountLocked} />
<ExpenseItemWrapper
index={i}
isAmountLocked={isAmountLocked}
isSubjectToTax={Boolean(props.taxType)}
/>
</div>
<div className="flex flex-col gap-1">
<Button
Expand Down Expand Up @@ -246,6 +250,7 @@ type ExpenseItemProps = {
index: number;
isAmountLocked?: boolean;
item: ExpenseForm['values']['expenseItems'][number];
isSubjectToTax?: boolean;
} & ReturnType<typeof getExpenseItemProps>;

function getExpenseItemProps(form: ExpenseForm) {
Expand All @@ -255,13 +260,14 @@ function getExpenseItemProps(form: ExpenseForm) {
};
}

function ExpenseItemWrapper(props: { index: number; isAmountLocked?: boolean }) {
function ExpenseItemWrapper(props: { index: number; isAmountLocked?: boolean; isSubjectToTax?: boolean }) {
const form = useFormikContext() as ExpenseForm;
return (
<ExpenseItem
index={props.index}
item={get(form.values, `expenseItems.${props.index}`)}
isAmountLocked={props.isAmountLocked}
isSubjectToTax={props.isSubjectToTax}
{...ExpenseItem.getFormProps(form)}
/>
);
Expand Down Expand Up @@ -384,7 +390,11 @@ const ExpenseItem = memoWithGetFormProps(function ExpenseItem(props: ExpenseItem
<div className="col-span-2 flex flex-col">
<FormField
disabled={props.isAmountLocked || props.isSubmitting}
label={intl.formatMessage({ defaultMessage: 'Amount', id: 'Fields.amount' })}
label={
props.isSubjectToTax
? intl.formatMessage({ defaultMessage: 'Gross Amount', id: 'bwZInO' })
: intl.formatMessage({ defaultMessage: 'Amount', id: 'Fields.amount' })
}
name={`expenseItems.${props.index}.amount.valueInCents`}
>
{({ field }) => (
Expand Down
153 changes: 153 additions & 0 deletions lib/graphql/schemaV2.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -654,6 +654,11 @@ interface Account {
"""
account: AccountReferenceInput

"""
An alternative to filter by accounts, both cannot be used together
"""
accounts: [AccountReferenceInput]

"""
Return expenses only for this host
"""
Expand Down Expand Up @@ -3195,6 +3200,11 @@ type Host implements Account & AccountWithContributions {
"""
account: AccountReferenceInput

"""
An alternative to filter by accounts, both cannot be used together
"""
accounts: [AccountReferenceInput]

"""
Return expenses only for this host
"""
Expand Down Expand Up @@ -7138,6 +7148,16 @@ type TransactionsImport {
"""
lastSyncCursor: String

"""
List of available accounts for the import
"""
plaidAccounts: [PlaidAccount]

"""
Assignments for the import, as a map of account id to legacy collective IDs. The `__default__` key can be use to set the default assignment.
"""
assignments: [TransactionsImportAssignment!]!

"""
Connected account linked to the import
"""
Expand Down Expand Up @@ -7166,6 +7186,11 @@ type TransactionsImport {
Search by text
"""
searchTerm: String

"""
Filter rows by plaid account id
"""
accountId: [NonEmptyString]
): TransactionsImportRowCollection!
stats: TransactionsImportStats
}
Expand All @@ -7184,6 +7209,52 @@ enum TransactionsImportType {
PLAID
}

type PlaidAccount {
accountId: String!
mask: String!
name: String!
officialName: String!
subtype: String!
type: PlaidAccountType!
}

enum PlaidAccountType {
"""
Investment
"""
investment

"""
Credit
"""
credit

"""
Depository
"""
depository

"""
Loan
"""
loan

"""
Brokerage
"""
brokerage

"""
Other
"""
other
}

type TransactionsImportAssignment {
importedAccountId: NonEmptyString!
accounts: [Account!]!
}

"""
A collection of "TransactionsImportRow"
"""
Expand Down Expand Up @@ -8435,6 +8506,11 @@ type Bot implements Account {
"""
account: AccountReferenceInput

"""
An alternative to filter by accounts, both cannot be used together
"""
accounts: [AccountReferenceInput]

"""
Return expenses only for this host
"""
Expand Down Expand Up @@ -9313,6 +9389,11 @@ type Collective implements Account & AccountWithHost & AccountWithContributions
"""
account: AccountReferenceInput

"""
An alternative to filter by accounts, both cannot be used together
"""
accounts: [AccountReferenceInput]

"""
Return expenses only for this host
"""
Expand Down Expand Up @@ -10740,6 +10821,11 @@ type Event implements Account & AccountWithHost & AccountWithContributions & Acc
"""
account: AccountReferenceInput

"""
An alternative to filter by accounts, both cannot be used together
"""
accounts: [AccountReferenceInput]

"""
Return expenses only for this host
"""
Expand Down Expand Up @@ -11887,6 +11973,11 @@ type Individual implements Account {
"""
account: AccountReferenceInput

"""
An alternative to filter by accounts, both cannot be used together
"""
accounts: [AccountReferenceInput]

"""
Return expenses only for this host
"""
Expand Down Expand Up @@ -13012,6 +13103,11 @@ type Organization implements Account & AccountWithContributions {
"""
account: AccountReferenceInput

"""
An alternative to filter by accounts, both cannot be used together
"""
accounts: [AccountReferenceInput]

"""
Return expenses only for this host
"""
Expand Down Expand Up @@ -14003,6 +14099,11 @@ type Vendor implements Account & AccountWithContributions {
"""
account: AccountReferenceInput

"""
An alternative to filter by accounts, both cannot be used together
"""
accounts: [AccountReferenceInput]

"""
Return expenses only for this host
"""
Expand Down Expand Up @@ -14815,6 +14916,11 @@ type Query {
"""
account: AccountReferenceInput

"""
An alternative to filter by accounts, both cannot be used together
"""
accounts: [AccountReferenceInput]

"""
Return expenses only for this host
"""
Expand Down Expand Up @@ -17639,6 +17745,11 @@ type Fund implements Account & AccountWithHost & AccountWithContributions {
"""
account: AccountReferenceInput

"""
An alternative to filter by accounts, both cannot be used together
"""
accounts: [AccountReferenceInput]

"""
Return expenses only for this host
"""
Expand Down Expand Up @@ -18664,6 +18775,11 @@ type Project implements Account & AccountWithHost & AccountWithContributions & A
"""
account: AccountReferenceInput

"""
An alternative to filter by accounts, both cannot be used together
"""
accounts: [AccountReferenceInput]

"""
Return expenses only for this host
"""
Expand Down Expand Up @@ -20729,6 +20845,11 @@ type Mutation {
The language to use in the Plaid Link flow. Defaults to "en".
"""
locale: Locale

"""
If true, the account selection flow will be enabled. Requires an `accessToken`.
"""
accountSelectionEnabled: Boolean
): PlaidLinkTokenCreateResponse!

"""
Expand Down Expand Up @@ -20766,6 +20887,21 @@ type Mutation {
connectedAccount: ConnectedAccountReferenceInput!
): TransactionsImport!

"""
Refresh the list of sub-accounts & other metadata by re-fetching the account info
"""
refreshPlaidAccount(
"""
The Plaid connected account to refresh
"""
connectedAccount: ConnectedAccountReferenceInput

"""
The transactions import to refresh
"""
transactionImport: TransactionsImportReferenceInput
): PlaidConnectAccountResponse!

"""
[Root only] Edits account flags (deleted, banned, archived, trusted host)
"""
Expand Down Expand Up @@ -20954,6 +21090,11 @@ type Mutation {
Name of the import (e.g. "Contributions May 2021", "Tickets for Mautic Conference 2024")
"""
name: NonEmptyString

"""
Assignments for the import
"""
assignments: [TransactionsImportAssignmentInput!]
): TransactionsImport!

"""
Expand Down Expand Up @@ -23234,6 +23375,18 @@ type BanAccountResponse {
accounts: [Account!]!
}

input TransactionsImportAssignmentInput {
"""
The ID of the account to assign the transactions to
"""
importedAccountId: NonEmptyString!

"""
The accounts to assign the transactions to
"""
accounts: [AccountReferenceInput!]!
}

input TransactionsImportRowCreateInput {
"""
The source id of the row
Expand Down
4 changes: 2 additions & 2 deletions lib/graphql/types/v2/gql.ts
Original file line number Diff line number Diff line change
Expand Up @@ -245,7 +245,7 @@ const documents = {
"\n mutation RejectVirtualCardRequest($virtualCardRequest: VirtualCardRequestReferenceInput!) {\n rejectVirtualCardRequest(virtualCardRequest: $virtualCardRequest) {\n id\n status\n }\n }\n": types.RejectVirtualCardRequestDocument,
"\n query VirtualCardDrawer($virtualCard: VirtualCardReferenceInput!) {\n virtualCard(virtualCard: $virtualCard) {\n id\n name\n last4\n data\n privateData\n provider\n spendingLimitAmount\n spendingLimitInterval\n spendingLimitRenewsOn\n remainingLimit\n currency\n createdAt\n status\n account {\n id\n name\n slug\n imageUrl\n ...AccountHoverCardFields\n }\n assignee {\n id\n name\n email\n slug\n imageUrl\n ...AccountHoverCardFields\n }\n host {\n id\n slug\n stripe {\n username\n }\n }\n }\n }\n \n": types.VirtualCardDrawerDocument,
"\n mutation UploadFile($files: [UploadFileInput!]!) {\n uploadFile(files: $files) {\n file {\n id\n url\n name\n type\n size\n }\n parsingResult {\n success\n message\n expense {\n confidence\n description\n date\n amount {\n valueInCents\n currency\n exchangeRate {\n value\n fromCurrency\n toCurrency\n date\n source\n isApproximate\n }\n }\n items {\n description\n incurredAt\n url\n amount {\n valueInCents\n currency\n }\n }\n }\n }\n }\n }\n": types.UploadFileDocument,
"\n mutation GeneratePlaidLinkToken(\n $host: AccountReferenceInput!\n $transactionImport: TransactionsImportReferenceInput\n $locale: Locale\n ) {\n generatePlaidLinkToken(host: $host, transactionImport: $transactionImport, locale: $locale) {\n linkToken\n expiration\n requestId\n hostedLinkUrl\n }\n }\n": types.GeneratePlaidLinkTokenDocument,
"\n mutation GeneratePlaidLinkToken(\n $host: AccountReferenceInput!\n $transactionImport: TransactionsImportReferenceInput\n $locale: Locale\n $accountSelectionEnabled: Boolean\n ) {\n generatePlaidLinkToken(\n host: $host\n transactionImport: $transactionImport\n locale: $locale\n accountSelectionEnabled: $accountSelectionEnabled\n ) {\n linkToken\n expiration\n requestId\n hostedLinkUrl\n }\n }\n": types.GeneratePlaidLinkTokenDocument,
"\n mutation ConnectPlaidAccount(\n $publicToken: String!\n $host: AccountReferenceInput!\n $sourceName: String\n $name: String\n ) {\n connectPlaidAccount(publicToken: $publicToken, host: $host, sourceName: $sourceName, name: $name) {\n connectedAccount {\n id\n }\n transactionsImport {\n id\n }\n }\n }\n": types.ConnectPlaidAccountDocument,
"\n query CollectiveContactPage($collectiveSlug: String!) {\n account(slug: $collectiveSlug, throwIfMissing: false) {\n id\n slug\n name\n type\n permissions {\n id\n contact {\n allowed\n }\n }\n description\n settings\n imageUrl\n twitterHandle\n features {\n id\n ...NavbarFields\n }\n }\n }\n \n": types.CollectiveContactPageDocument,
"\n mutation ConfirmEmail($token: NonEmptyString!) {\n confirmEmail(token: $token) {\n sessionToken\n individual {\n id\n email\n }\n }\n }\n": types.ConfirmEmailDocument,
Expand Down Expand Up @@ -1202,7 +1202,7 @@ export function graphql(source: "\n mutation UploadFile($files: [UploadFileInpu
/**
* The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
*/
export function graphql(source: "\n mutation GeneratePlaidLinkToken(\n $host: AccountReferenceInput!\n $transactionImport: TransactionsImportReferenceInput\n $locale: Locale\n ) {\n generatePlaidLinkToken(host: $host, transactionImport: $transactionImport, locale: $locale) {\n linkToken\n expiration\n requestId\n hostedLinkUrl\n }\n }\n"): (typeof documents)["\n mutation GeneratePlaidLinkToken(\n $host: AccountReferenceInput!\n $transactionImport: TransactionsImportReferenceInput\n $locale: Locale\n ) {\n generatePlaidLinkToken(host: $host, transactionImport: $transactionImport, locale: $locale) {\n linkToken\n expiration\n requestId\n hostedLinkUrl\n }\n }\n"];
export function graphql(source: "\n mutation GeneratePlaidLinkToken(\n $host: AccountReferenceInput!\n $transactionImport: TransactionsImportReferenceInput\n $locale: Locale\n $accountSelectionEnabled: Boolean\n ) {\n generatePlaidLinkToken(\n host: $host\n transactionImport: $transactionImport\n locale: $locale\n accountSelectionEnabled: $accountSelectionEnabled\n ) {\n linkToken\n expiration\n requestId\n hostedLinkUrl\n }\n }\n"): (typeof documents)["\n mutation GeneratePlaidLinkToken(\n $host: AccountReferenceInput!\n $transactionImport: TransactionsImportReferenceInput\n $locale: Locale\n $accountSelectionEnabled: Boolean\n ) {\n generatePlaidLinkToken(\n host: $host\n transactionImport: $transactionImport\n locale: $locale\n accountSelectionEnabled: $accountSelectionEnabled\n ) {\n linkToken\n expiration\n requestId\n hostedLinkUrl\n }\n }\n"];
/**
* The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
*/
Expand Down
Loading

0 comments on commit d42b6d3

Please sign in to comment.