Skip to content

Commit

Permalink
follow up
Browse files Browse the repository at this point in the history
  • Loading branch information
znarf committed Mar 4, 2024
1 parent 2f26247 commit 384de50
Show file tree
Hide file tree
Showing 7 changed files with 38 additions and 32 deletions.
2 changes: 1 addition & 1 deletion scripts/ledger/refund-host-fee-on-transaction.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ const main = async () => {
`Refunding host fee for transaction ${transactionGroup} (${transaction.description}) on behalf of ${userCollectiveSlug}`,
);
if (!DRY_RUN) {
await refundHostFee(transaction, user, 0, uuid(), null);
await refundHostFee(transaction, user, 0, uuid());
}
};

Expand Down
2 changes: 1 addition & 1 deletion scripts/taxes/add-tax-on-expense.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ const main = async () => {
}
}

const tax = { type: 'GST', rate: 0.15, percentage: 15 } as ExpenseTaxDefinition;
const tax = { type: 'GST', id: 'GST', rate: 0.15, percentage: 15 } as ExpenseTaxDefinition;
const taxAmountFromExpense = getTaxAmount(expense.amount, tax.rate);
const taxAmountFromItems = sum(expense.items.map(i => getTaxAmount(i.amount, tax.rate)));
if (taxAmountFromExpense !== taxAmountFromItems) {
Expand Down
38 changes: 20 additions & 18 deletions server/lib/payments.ts
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,10 @@ export function findPaymentMethodProvider(
* field. Which means that the query to select the order must include
* the `PaymentMethods` table.
*/
export async function processOrder(order: OrderModelInterface, options): Promise<TransactionInterface | void> {
export async function processOrder(
order: OrderModelInterface,
options: { isAddedFund?: boolean; invoiceTemplate?: string } = {},
): Promise<TransactionInterface | void> {
const paymentMethodProvider = findPaymentMethodProvider(order.paymentMethod);
if (get(paymentMethodProvider, 'features.waitToCharge') && !get(order, 'paymentMethod.paid')) {
return;
Expand Down Expand Up @@ -316,8 +319,7 @@ async function refundPaymentProcessorFee(
user: User,
refundedPaymentProcessorFee: number,
transactionGroup: string,
data: Record<string, never> = {},
clearedAt: Date = null,
clearedAt?: Date,
): Promise<void> {
const isLegacyPaymentProcessorFee = Boolean(transaction.paymentProcessorFeeInHostCurrency);

Expand Down Expand Up @@ -348,13 +350,13 @@ async function refundPaymentProcessorFee(

if (processorFeeTransaction) {
const processorFeeRefund = {
...buildRefundForTransaction(processorFeeTransaction, user, data),
...buildRefundForTransaction(processorFeeTransaction, user),
TransactionGroup: transactionGroup,
clearedAt,
};

const processorFeeRefundTransaction = await Transaction.createDoubleEntry(processorFeeRefund);
await associateTransactionRefundId(processorFeeTransaction, processorFeeRefundTransaction, data);
await associateTransactionRefundId(processorFeeTransaction, processorFeeRefundTransaction);
}
}

Expand All @@ -377,13 +379,12 @@ export async function refundHostFee(
user: User,
refundedPaymentProcessorFee: number,
transactionGroup: string,
data: Record<string, never> = {},
clearedAt: Date = null,
clearedAt?: Date,
): Promise<void> {
const hostFeeTransaction = await transaction.getHostFeeTransaction();
const buildRefund = transaction => {
return {
...buildRefundForTransaction(transaction, user, data, refundedPaymentProcessorFee),
...buildRefundForTransaction(transaction, user, null, refundedPaymentProcessorFee),
TransactionGroup: transactionGroup,
clearedAt,
};
Expand All @@ -392,14 +393,14 @@ export async function refundHostFee(
if (hostFeeTransaction) {
const hostFeeRefund = buildRefund(hostFeeTransaction);
const hostFeeRefundTransaction = await Transaction.createDoubleEntry(hostFeeRefund);
await associateTransactionRefundId(hostFeeTransaction, hostFeeRefundTransaction, data);
await associateTransactionRefundId(hostFeeTransaction, hostFeeRefundTransaction);

// Refund Host Fee Share
const hostFeeShareTransaction = await transaction.getHostFeeShareTransaction();
if (hostFeeShareTransaction) {
const hostFeeShareRefund = buildRefund(hostFeeShareTransaction);
const hostFeeShareRefundTransaction = await Transaction.createDoubleEntry(hostFeeShareRefund);
await associateTransactionRefundId(hostFeeShareTransaction, hostFeeShareRefundTransaction, data);
await associateTransactionRefundId(hostFeeShareTransaction, hostFeeShareRefundTransaction);

// Refund Host Fee Share Debt
const hostFeeShareDebtTransaction = await transaction.getHostFeeShareDebtTransaction();
Expand All @@ -420,7 +421,7 @@ export async function refundHostFee(

const hostFeeShareDebtRefund = buildRefund(hostFeeShareDebtTransaction);
const hostFeeShareDebtRefundTransaction = await Transaction.createDoubleEntry(hostFeeShareDebtRefund);
await associateTransactionRefundId(hostFeeShareDebtTransaction, hostFeeShareDebtRefundTransaction, data);
await associateTransactionRefundId(hostFeeShareDebtTransaction, hostFeeShareDebtRefundTransaction);
await TransactionSettlement.createForTransaction(
hostFeeShareDebtRefundTransaction,
hostFeeShareRefundSettlementStatus,
Expand All @@ -434,18 +435,17 @@ async function refundTax(
transaction: TransactionInterface,
user: User,
transactionGroup: string,
data: Record<string, never> = {},
clearedAt: Date = null,
clearedAt?: Date,
): Promise<void> {
const taxTransaction = await transaction.getTaxTransaction();
if (taxTransaction) {
const taxRefundData = {
...buildRefundForTransaction(taxTransaction, user, data),
...buildRefundForTransaction(taxTransaction, user),
TransactionGroup: transactionGroup,
clearedAt,
};
const taxRefundTransaction = await Transaction.createDoubleEntry(taxRefundData);
await associateTransactionRefundId(taxTransaction, taxRefundTransaction, data);
await associateTransactionRefundId(taxTransaction, taxRefundTransaction);
}
}

Expand Down Expand Up @@ -542,13 +542,13 @@ export async function createRefundTransaction(
}

// Refund Payment Processor Fee
await refundPaymentProcessorFee(transaction, user, refundedPaymentProcessorFee, transactionGroup, {}, clearedAt);
await refundPaymentProcessorFee(transaction, user, refundedPaymentProcessorFee, transactionGroup, clearedAt);

// Refund Host Fee
await refundHostFee(transaction, user, refundedPaymentProcessorFee, transactionGroup, {}, clearedAt);
await refundHostFee(transaction, user, refundedPaymentProcessorFee, transactionGroup, clearedAt);

// Refund Tax
await refundTax(transaction, user, transactionGroup, {}, clearedAt);
await refundTax(transaction, user, transactionGroup, clearedAt);

// Refund main transaction
const creditTransactionRefund = buildRefund(transaction);
Expand Down Expand Up @@ -1128,9 +1128,11 @@ export const isPlatformTipEligible = async (order: OrderModelInterface): Promise
}

// Platform Tips opt out
/*
if (!isNil(order.collective.settings?.platformTips)) {
return order.collective.settings.platformTips;
}
*/

// Make sure payment method is available
if (!order.paymentMethod && order.PaymentMethodId) {
Expand Down
1 change: 0 additions & 1 deletion server/models/Collective.ts
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,6 @@ type Settings = {
payoutsTwoFactorAuth?: {
enabled?: boolean;
};
platformTips?: boolean;
customEmailMessage?: string;
} & TaxSettings;

Expand Down
9 changes: 5 additions & 4 deletions server/models/Expense.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,10 +63,11 @@ const PRIVATE_MESSAGE_SANITIZE_OPTS = buildSanitizerOptions({
});

export type ExpenseTaxDefinition = {
type: TaxType;
id?: TaxType | `${TaxType}`; // deprecated
type: TaxType | `${TaxType}`;
rate: number;
percentage?: number; // deprecated
idNumber?: string; // should be mandatory
percentage?: number; // deprecated, https://github.com/opencollective/opencollective/issues/5389
idNumber?: string;
};

class Expense extends Model<InferAttributes<Expense>, InferCreationAttributes<Expense>> {
Expand All @@ -82,7 +83,7 @@ class Expense extends Model<InferAttributes<Expense>, InferCreationAttributes<Ex
public declare RecurringExpenseId: ForeignKey<RecurringExpense['id']>;
public declare AccountingCategoryId: ForeignKey<AccountingCategory['id']>;

public declare payeeLocation: Location; // TODO This can be typed
public declare payeeLocation: Location;
public declare data: Record<string, unknown> & {
batchGroup?: BatchGroup;
quote?: ExpenseDataQuoteV2 | ExpenseDataQuoteV3;
Expand Down
13 changes: 7 additions & 6 deletions server/models/Transaction.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ import Activity from './Activity';
import Collective from './Collective';
import CustomDataTypes from './DataTypes';
import type Expense from './Expense';
import type { ExpenseTaxDefinition } from './Expense';
import Order, { OrderModelInterface, OrderTax } from './Order';
import PaymentMethod, { PaymentMethodModelInterface } from './PaymentMethod';
import PayoutMethod, { PayoutMethodTypes } from './PayoutMethod';
Expand All @@ -51,7 +52,7 @@ const { CONTRIBUTION, EXPENSE, ADDED_FUNDS } = TransactionKind;

const debug = debugLib('models:Transaction');

type Tax = Partial<OrderTax> & { rate?: number; idNumber?: string };
type Tax = OrderTax | ExpenseTaxDefinition;

export type TransactionData = {
balanceTransaction?: Stripe.BalanceTransaction;
Expand Down Expand Up @@ -81,7 +82,6 @@ export type TransactionData = {
refundReason?: string;
refundTransactionId?: TransactionInterface['id'];
review?: Stripe.Event; // Why not Stripe.Review? Who knows
settled?: boolean;
tax?: Tax;
taxAmountRemovedFromMigration?: number;
taxMigration?: string;
Expand Down Expand Up @@ -589,7 +589,7 @@ Transaction.prototype.getRefundTransaction = function (): Promise<TransactionInt

Transaction.prototype.hasPlatformTip = function (): boolean {
return Boolean(
(this.data?.hasPlatformTip || this.data?.isFeesOnTop) &&
this.data?.hasPlatformTip &&
this.kind !== TransactionKind.PLATFORM_TIP &&
this.kind !== TransactionKind.PLATFORM_TIP_DEBT,
);
Expand Down Expand Up @@ -1551,9 +1551,10 @@ Transaction.fetchHost = async (
host = await Collective.findByPk(transaction.HostCollectiveId);
}
if (!host) {
console.warn(`transaction.HostCollectiveId should always bet set`);
const collective = await Collective.findByPk(transaction.CollectiveId);
host = await collective.getHostCollective();
throw new Error(`transaction.HostCollectiveId should always bet set`);
// console.warn(`transaction.HostCollectiveId should always bet set`);
// const collective = await Collective.findByPk(transaction.CollectiveId);
// host = await collective.getHostCollective();
}
return host;
};
Expand Down
5 changes: 4 additions & 1 deletion server/paymentProviders/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,10 @@ export interface PaymentProviderService {
/**
* Triggers the payment for this order and updates it accordingly
*/
processOrder(order: OrderModelInterface, options?: Record<string, never>): Promise<TransactionInterface | void>;
processOrder(
order: OrderModelInterface,
options?: { isAddedFund?: boolean; invoiceTemplate?: string },
): Promise<TransactionInterface | void>;

/**
* Refunds a transaction processed with this payment provider service
Expand Down

0 comments on commit 384de50

Please sign in to comment.