diff --git a/src/backend/odoo/account.ts b/src/backend/odoo/account.ts index 7b156b8..ac9ad22 100644 --- a/src/backend/odoo/account.ts +++ b/src/backend/odoo/account.ts @@ -1,5 +1,3 @@ -import * as t from '../../type' - import { BridgeObject } from '..' diff --git a/src/backend/odoo/paymentRequest.ts b/src/backend/odoo/paymentRequest.ts new file mode 100644 index 0000000..dcd1567 --- /dev/null +++ b/src/backend/odoo/paymentRequest.ts @@ -0,0 +1,105 @@ +import { BridgeObject } from ".." + + +export default class PaymentRequest extends BridgeObject { + + get isPaymentRequest() { + return true + } + + get id() { + return this.jsonData.id + } + + get amount() { + // Format amount with 2 decimal places (e.g., 40 -> "40.00") + return Number(this.jsonData.amount).toFixed(2) + } + + get message() { + return this.jsonData.message + } + + get state() { + return this.jsonData.state + } + + get creatorWalletUri() { + return this.jsonData.creator_wallet_uri + } + + get creatorName() { + return this.jsonData.creator_name + } + + get date() { + return new Date(this.jsonData.create_date * 1000) + } + + get isCreator() { + return this.creatorWalletUri === this.parent.internalId + } + + get senderWalletUri() { + return this.jsonData.sender_wallet_uri + } + + get receiverWalletUri() { + return this.jsonData.receiver_wallet_uri + } + + get isSender() { + return this.senderWalletUri === this.parent.internalId + } + + get isReceiver() { + return this.receiverWalletUri === this.parent.internalId + } + + get related() { + // Si je suis le sender, afficher le receiver, sinon afficher le sender + if (this.isSender) { + return this.jsonData.receiver_name || this.receiverWalletUri + } + return this.jsonData.sender_name || this.senderWalletUri + } + + get description() { + return this.message + } + + public async cancel(reason?: string) { + return this._updateStatus("cancelled", reason) + } + + public async refuse(reason: string) { + return this._updateStatus("refused", reason) + } + + public async markAsPaid(txId: string) { + return this._updateStatus("paid", txId) + } + + private async _updateStatus(status: string, message?: string) { + const currencyId = this.parent.getCurrencyId() + const backendType = this.parent.internalId.split(':')[0] + const currency_uri = `${backendType}:${currencyId}` + + const res = await this.backends.odoo.$post( + "/payment_request/update-payment-request", + { + wallet_uri: this.parent.internalId, + currency_uri: currency_uri, + payment_request_id: this.id, + status, + message, + } + ) + if (!res) { + throw new Error( + `Failed to update payment request status to ${status}` + ) + } + return + } +} diff --git a/src/backend/odoo/recurrentContract.ts b/src/backend/odoo/recurrentContract.ts new file mode 100644 index 0000000..3613438 --- /dev/null +++ b/src/backend/odoo/recurrentContract.ts @@ -0,0 +1,113 @@ +import { BridgeObject } from ".." +import { t } from "../.." + + +export default class RecurrentContract extends BridgeObject { + + get isRecurrentContract() { + return true + } + + get id() { + return this.jsonData.id + } + + get amount(): string { + return Number(this.jsonData.amount).toFixed(2) + } + + get message(): string { + return this.jsonData.message + } + + get state(): string { + return this.jsonData.state + } + + get creatorWalletUri(): string { + return this.jsonData.creator_wallet_uri + } + + get creatorName(): string { + return this.jsonData.creator_name + } + + get date(): Date { + return new Date(this.jsonData.create_date * 1000) + } + + get isCreator(): boolean { + return this.creatorWalletUri === this.parent.internalId + } + + get senderWalletUri(): string { + return this.jsonData.sender_wallet_uri + } + + get senderName(): string { + return this.jsonData.sender_name + } + + get receiverWalletUri(): string { + return this.jsonData.receiver_wallet_uri + } + + get receiverName(): string { + return this.jsonData.receiver_name + } + + get isSender(): boolean { + return this.senderWalletUri === this.parent.internalId + } + + get isReceiver(): boolean { + return this.receiverWalletUri === this.parent.internalId + } + + get related(): string { + if (this.isSender) { + return this.receiverName || this.receiverWalletUri + } + return this.senderName || this.senderWalletUri + } + + get description(): string { + return this.message + } + + get dateStart(): string | null { + return this.jsonData.date_start + } + + get dateEnd(): string | null { + return this.jsonData.date_end + } + + get recurringRuleType(): t.RecurringRuleType { + return this.jsonData.recurring_rule_type + } + + get recurringInterval(): number { + return this.jsonData.recurring_interval + } + + get nextExecutionDate(): string | null { + return this.jsonData.recurring_next_date + } + + public async delete(): Promise { + const currencyId = this.parent.getCurrencyId() + const backendType = this.parent.internalId.split(':')[0] + const currency_uri = `${backendType}:${currencyId}` + + const res = await this.backends.odoo.$delete( + "/payment_request_recurrent_contract/delete-payment-request-recurrent-contracts", + { + wallet_uri: this.parent.internalId, + currency_uri: currency_uri, + payment_request_ids: [this.id], + } + ) + return res === true + } +} diff --git a/src/backend/odoo/userAccount.ts b/src/backend/odoo/userAccount.ts index 6621032..464aeb4 100644 --- a/src/backend/odoo/userAccount.ts +++ b/src/backend/odoo/userAccount.ts @@ -1,13 +1,119 @@ import { BridgeObject } from '..' import { t } from '../..' +import PaymentRequest from './paymentRequest' +import RecurrentContract from './recurrentContract' export default abstract class UserAccount extends BridgeObject { abstract internalId: string + abstract getAccounts(): Promise + abstract getCurrencyId(): string get isTopUpAllowed() { return this.jsonData?.is_topup_allowed !== false } + public async getPaymentRequests(state: string[]): Promise { + const currencyId = this.getCurrencyId() + const backendType = this.internalId.split(':')[0] + const currency_uri = `${backendType}:${currencyId}` + + const requests = await this.backends.odoo.$get( + '/payment_request/list-payment-requests', + { + wallet_uri: this.internalId, + currency_uri: currency_uri, + state: state, + } + ) + return requests.map((e: any) => new PaymentRequest(this.backends, this, e)) + } + + public async createPaymentRequest( + requests: Array<{ + sender_wallet_uri: string + receiver_wallet_uri: string + amount: number + message?: string + }> + ): Promise { + const currencyId = this.getCurrencyId() + const backendType = this.internalId.split(':')[0] + const currency_uri = `${backendType}:${currencyId}` + + const res = await this.backends.odoo.$post( + '/payment_request/create-payment-request', + { + currency_uri: currency_uri, + creator_wallet_uri: this.internalId, + requests: requests.map(req => ({ + sender_wallet_uri: req.sender_wallet_uri, + receiver_wallet_uri: req.receiver_wallet_uri, + amount: req.amount, + message: req.message || null, + })), + } + ) + if (!res || !Array.isArray(res)) { + throw new Error('Failed to create payment request') + } + return res + } + + public async getRecurrentContracts(state: string[]): Promise { + const currencyId = this.getCurrencyId() + const backendType = this.internalId.split(':')[0] + const currency_uri = `${backendType}:${currencyId}` + + const contracts = await this.backends.odoo.$get( + '/payment_request_recurrent_contract/list-payment-request-recurrent-contracts', + { + wallet_uri: this.internalId, + currency_uri: currency_uri, + state: state, + } + ) + return contracts.map((e: any) => new RecurrentContract(this.backends, this, e)) + } + + public async createRecurrentContract( + contracts: Array<{ + sender_wallet_uri: string + receiver_wallet_uri: string + amount: number + message?: string + date_start: string + date_end?: string + recurring_rule_type: t.RecurringRuleType + recurring_interval: number + }> + ): Promise { + const currencyId = this.getCurrencyId() + const backendType = this.internalId.split(':')[0] + const currency_uri = `${backendType}:${currencyId}` + + const res = await this.backends.odoo.$post( + '/payment_request_recurrent_contract/create-payment-request-recurrent-contract', + { + currency_uri: currency_uri, + creator_wallet_uri: this.internalId, + contracts: contracts.map(contract => ({ + sender_wallet_uri: contract.sender_wallet_uri, + receiver_wallet_uri: contract.receiver_wallet_uri, + amount: contract.amount, + message: contract.message || null, + date_start: contract.date_start, + date_end: contract.date_end || null, + recurring_rule_type: contract.recurring_rule_type, + recurring_interval: contract.recurring_interval, + })), + } + ) + if (!res || !Array.isArray(res)) { + throw new Error('Failed to create recurrent contract') + } + return res + } + } diff --git a/src/type.ts b/src/type.ts index e2bcc90..55af32e 100644 --- a/src/type.ts +++ b/src/type.ts @@ -68,6 +68,42 @@ export interface ITransaction extends IBridge { export interface ICreditRequest extends ITransaction {} +export interface IPaymentRequest extends IBridge { + id: number + amount: string + message: string + state: string + creatorWalletUri: string + senderWalletUri: string + receiverWalletUri: string + + cancel(): Promise + refuse(reason: string): Promise + markAsPaid(txId: string): Promise +} + + +export type RecurringRuleType = 'daily' | 'weekly' | 'monthly' | 'yearly' + + +export interface IRecurrentContract extends IBridge { + id: number + amount: string + message: string + state: string + creatorWalletUri: string + senderWalletUri: string + receiverWalletUri: string + dateStart: string | null + dateEnd: string | null + recurringRuleType: RecurringRuleType + recurringInterval: number + nextExecutionDate: string | null + + delete(): Promise +} + + export interface IContact extends IBridge { /**