Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
  • Loading branch information
kewitz committed Feb 7, 2025
1 parent 1ef63a2 commit fb7d0c3
Show file tree
Hide file tree
Showing 4 changed files with 54 additions and 6 deletions.
1 change: 1 addition & 0 deletions server/graphql/loaders/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ export const loaders = req => {
// Payout method
context.loaders.PayoutMethod.paypalByCollectiveId = generateCollectivePaypalPayoutMethodsLoader();
context.loaders.PayoutMethod.byCollectiveId = generateCollectivePayoutMethodsLoader();
context.loaders.PayoutMethod.allByCollectiveId = generateCollectivePayoutMethodsLoader({ onlySaved: false });

// Virtual Card
context.loaders.VirtualCard.byCollectiveId = generateCollectiveVirtualCardLoader();
Expand Down
10 changes: 7 additions & 3 deletions server/graphql/loaders/payout-method.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,16 @@ export const generateCollectivePaypalPayoutMethodsLoader = (): DataLoader<number
/**
* Loader for all collective's payout methods
*/
export const generateCollectivePayoutMethodsLoader = (): DataLoader<number, PayoutMethod[]> => {
export function generateCollectivePayoutMethodsLoader({ onlySaved = true } = {}): DataLoader<number, PayoutMethod[]> {
return new DataLoader(async (collectiveIds: number[]) => {
const where = { CollectiveId: { [Op.in]: collectiveIds } };
if (onlySaved) {
where['isSaved'] = true;
}
const payoutMethods = await PayoutMethod.findAll({
where: { CollectiveId: { [Op.in]: collectiveIds }, isSaved: true },
where,
});

return sortResultsArray(collectiveIds, payoutMethods, pm => pm.CollectiveId);
});
};
}
23 changes: 20 additions & 3 deletions server/graphql/v2/interface/Account.ts
Original file line number Diff line number Diff line change
Expand Up @@ -441,6 +441,13 @@ const accountFieldsDefinition = () => ({
payoutMethods: {
type: new GraphQLList(GraphQLPayoutMethod),
description: 'The list of payout methods that this account can use to get paid',
args: {
includeArchived: {
type: GraphQLBoolean,
defaultValue: false,
description: 'Whether to include archived payout methods',
},
},
},
paymentMethods: {
type: new GraphQLList(GraphQLPaymentMethod),
Expand Down Expand Up @@ -1228,7 +1235,14 @@ export const AccountFields = {
type: new GraphQLList(GraphQLPayoutMethod),
description:
'The list of payout methods that this collective can use to get paid. In most cases, admin only and scope: "expenses".',
async resolve(collective, _, req) {
args: {
includeArchived: {
type: GraphQLBoolean,
defaultValue: false,
description: 'Whether to include archived payout methods',
},
},
async resolve(collective, args, req) {
// Scope check is a a bit more complex because we have to accomodate the case where payoutMethods are public
if (
req.remoteUser?.isAdminOfCollective(collective) &&
Expand All @@ -1238,13 +1252,16 @@ export const AccountFields = {
return null;
}

const loader = args.includeArchived
? req.loaders.PayoutMethod.allByCollectiveId
: req.loaders.PayoutMethod.byCollectiveId;
if (req.remoteUser?.isAdminOfCollective(collective)) {
return req.loaders.PayoutMethod.byCollectiveId.load(collective.id);
return loader.load(collective.id);
}

// Exception for Fiscal Hosts so people can post Expense accross hosts
if (collective.isHostAccount) {
const payoutMethods = await req.loaders.PayoutMethod.byCollectiveId.load(collective.id);
const payoutMethods = await loader.load(collective.id);
for (const payoutMethod of payoutMethods) {
allowContextPermission(req, PERMISSION_TYPE.SEE_PAYOUT_METHOD_DETAILS, payoutMethod.id);
}
Expand Down
26 changes: 26 additions & 0 deletions server/graphql/v2/mutation/PayoutMethodMutations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,32 @@ const payoutMethodMutations = {
return payoutMethod.update({ isSaved: false });
},
},
restorePayoutMethod: {
description: 'Restore the given payout method. Scope: "expenses".',
type: new GraphQLNonNull(GraphQLPayoutMethod),
args: {
payoutMethodId: {
type: new GraphQLNonNull(GraphQLString),
},
},
async resolve(_: void, args, req: express.Request): Promise<Record<string, unknown>> {
checkRemoteUserCanUseExpenses(req);

const pmId = idDecode(args.payoutMethodId, IDENTIFIER_TYPES.PAYOUT_METHOD);
const payoutMethod = await req.loaders.PayoutMethod.byId.load(pmId);

if (!payoutMethod) {
throw new NotFound('This payout method does not exist');
}

const collective = await req.loaders.Collective.byId.load(payoutMethod.CollectiveId);
if (!req.remoteUser.isAdminOfCollective(collective)) {
throw new Forbidden();
}

return payoutMethod.update({ isSaved: true });
},
},
};

export default payoutMethodMutations;

0 comments on commit fb7d0c3

Please sign in to comment.