Update transaction amount to bigint
This commit is contained in:
parent
bec18b925b
commit
dcb78d2252
|
|
@ -20,7 +20,7 @@ class StoreTransactionRequest extends FormRequest
|
|||
'description' => ['required', 'string'],
|
||||
'description_iv' => ['required', 'string', 'size:16'],
|
||||
'transaction_date' => ['required', 'date'],
|
||||
'amount' => ['required', 'numeric'],
|
||||
'amount' => ['required', 'integer'],
|
||||
'currency_code' => ['required', 'string', 'size:3'],
|
||||
'notes' => ['nullable', 'string'],
|
||||
'notes_iv' => ['nullable', 'string', 'size:16'],
|
||||
|
|
@ -39,7 +39,7 @@ class StoreTransactionRequest extends FormRequest
|
|||
'transaction_date.required' => 'The transaction date is required.',
|
||||
'transaction_date.date' => 'The transaction date must be a valid date.',
|
||||
'amount.required' => 'The amount is required.',
|
||||
'amount.numeric' => 'The amount must be a number.',
|
||||
'amount.integer' => 'The amount must be an integer.',
|
||||
'currency_code.required' => 'The currency code is required.',
|
||||
'currency_code.size' => 'The currency code must be exactly 3 characters.',
|
||||
'notes_iv.size' => 'The notes IV must be exactly 16 characters.',
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ class Transaction extends Model
|
|||
{
|
||||
return [
|
||||
'transaction_date' => 'date',
|
||||
'amount' => 'decimal:2',
|
||||
'amount' => 'integer',
|
||||
];
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ class TransactionFactory extends Factory
|
|||
'description' => fake()->sentence(),
|
||||
'description_iv' => fake()->regexify('[A-Za-z0-9]{16}'),
|
||||
'transaction_date' => fake()->dateTimeBetween('-1 year', 'now'),
|
||||
'amount' => fake()->randomFloat(2, -1000, 1000),
|
||||
'amount' => fake()->numberBetween(-100000, 100000),
|
||||
'currency_code' => fake()->randomElement(['USD', 'EUR', 'GBP', 'JPY']),
|
||||
'notes' => fake()->optional()->paragraph(),
|
||||
'notes_iv' => fake()->optional()->regexify('[A-Za-z0-9]{16}'),
|
||||
|
|
|
|||
|
|
@ -11,15 +11,21 @@ return new class extends Migration
|
|||
*/
|
||||
public function up(): void
|
||||
{
|
||||
// Drop the existing id column and recreate it as UUID
|
||||
Schema::table('transactions', function (Blueprint $table) {
|
||||
// Drop the existing auto-increment id
|
||||
$table->dropColumn('id');
|
||||
});
|
||||
Schema::dropIfExists('transactions');
|
||||
|
||||
Schema::table('transactions', function (Blueprint $table) {
|
||||
// Add new UUID id as primary key
|
||||
$table->uuid('id')->primary()->first();
|
||||
Schema::create('transactions', function (Blueprint $table) {
|
||||
$table->uuid('id')->primary();
|
||||
$table->foreignId('user_id')->constrained()->onDelete('cascade');
|
||||
$table->foreignId('account_id')->constrained()->onDelete('cascade');
|
||||
$table->foreignId('category_id')->nullable()->constrained()->onDelete('cascade');
|
||||
$table->text('description');
|
||||
$table->string('description_iv', 16);
|
||||
$table->date('transaction_date');
|
||||
$table->decimal('amount', 15, 2);
|
||||
$table->string('currency_code', 3);
|
||||
$table->text('notes')->nullable();
|
||||
$table->string('notes_iv', 16)->nullable();
|
||||
$table->timestamps();
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,30 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
DB::table('transactions')->truncate();
|
||||
|
||||
Schema::table('transactions', function (Blueprint $table) {
|
||||
$table->bigInteger('amount')->change();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::table('transactions', function (Blueprint $table) {
|
||||
$table->decimal('amount', 15, 2)->change();
|
||||
});
|
||||
}
|
||||
};
|
||||
|
|
@ -1,4 +1,5 @@
|
|||
import { CategorySelect } from '@/components/transactions/category-select';
|
||||
import { AmountInput } from '@/components/ui/amount-input';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import {
|
||||
Dialog,
|
||||
|
|
@ -53,7 +54,7 @@ export function EditTransactionDialog({
|
|||
const { isKeySet } = useEncryptionKey();
|
||||
const [transactionDate, setTransactionDate] = useState('');
|
||||
const [description, setDescription] = useState('');
|
||||
const [amount, setAmount] = useState('');
|
||||
const [amount, setAmount] = useState<number>(0);
|
||||
const [accountId, setAccountId] = useState<string>('');
|
||||
const [categoryId, setCategoryId] = useState<string>('null');
|
||||
const [notes, setNotes] = useState('');
|
||||
|
|
@ -78,7 +79,7 @@ export function EditTransactionDialog({
|
|||
const today = new Date().toISOString().split('T')[0];
|
||||
setTransactionDate(today);
|
||||
setDescription('');
|
||||
setAmount('');
|
||||
setAmount(0);
|
||||
setAccountId(accounts.length > 0 ? String(accounts[0].id) : '');
|
||||
setCategoryId('null');
|
||||
setNotes('');
|
||||
|
|
@ -142,7 +143,7 @@ export function EditTransactionDialog({
|
|||
toast.error('Description is required');
|
||||
return;
|
||||
}
|
||||
if (!amount || parseFloat(amount) === 0) {
|
||||
if (amount === 0) {
|
||||
toast.error('Amount is required');
|
||||
return;
|
||||
}
|
||||
|
|
@ -377,35 +378,23 @@ export function EditTransactionDialog({
|
|||
Amount
|
||||
</Label>
|
||||
{mode === 'create' ? (
|
||||
<>
|
||||
<Input
|
||||
id="amount"
|
||||
type="number"
|
||||
step="0.01"
|
||||
value={amount}
|
||||
onChange={(e) =>
|
||||
setAmount(e.target.value)
|
||||
}
|
||||
placeholder="0.00"
|
||||
disabled={isSubmitting}
|
||||
required
|
||||
/>
|
||||
{selectedAccount && (
|
||||
<p className="text-xs text-muted-foreground">
|
||||
Currency:{' '}
|
||||
{selectedAccount.currency_code}
|
||||
</p>
|
||||
)}
|
||||
</>
|
||||
<AmountInput
|
||||
id="amount"
|
||||
value={amount}
|
||||
onChange={setAmount}
|
||||
currencyCode={
|
||||
selectedAccount?.currency_code || 'USD'
|
||||
}
|
||||
disabled={isSubmitting}
|
||||
required
|
||||
/>
|
||||
) : (
|
||||
<div className="text-sm font-medium">
|
||||
{transaction &&
|
||||
new Intl.NumberFormat('en-US', {
|
||||
style: 'currency',
|
||||
currency: transaction.currency_code,
|
||||
}).format(
|
||||
parseFloat(transaction.amount),
|
||||
)}
|
||||
}).format(transaction.amount / 100)}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@ export function ImportStepPreview({
|
|||
return new Intl.NumberFormat('en-US', {
|
||||
style: 'currency',
|
||||
currency: currencyCode,
|
||||
}).format(amount);
|
||||
}).format(amount / 100);
|
||||
};
|
||||
|
||||
const formatDate = (dateStr: string): string => {
|
||||
|
|
|
|||
|
|
@ -175,7 +175,8 @@ export function createTransactionColumns({
|
|||
return <div className="w-full text-right">Amount</div>;
|
||||
},
|
||||
cell: ({ row }) => {
|
||||
const amount = parseFloat(row.getValue('amount'));
|
||||
const amountInCents = row.getValue('amount') as number;
|
||||
const amount = amountInCents / 100;
|
||||
const currencyCode = row.original.currency_code;
|
||||
|
||||
const formatted = new Intl.NumberFormat('en-US', {
|
||||
|
|
@ -200,7 +201,7 @@ export function createTransactionColumns({
|
|||
size: 35,
|
||||
maxSize: 35,
|
||||
minSize: 35,
|
||||
meta: {
|
||||
meta: {
|
||||
cellClassName: '!w-[35px] !max-w-[35px] !min-w-[35px] !p-0 whitespace-normal',
|
||||
cellStyle: { width: '35px', maxWidth: '35px', minWidth: '35px', padding: 0 }
|
||||
},
|
||||
|
|
|
|||
|
|
@ -0,0 +1,123 @@
|
|||
import * as React from 'react';
|
||||
|
||||
import {
|
||||
InputGroup,
|
||||
InputGroupAddon,
|
||||
InputGroupInput,
|
||||
InputGroupText,
|
||||
} from '@/components/ui/input-group';
|
||||
|
||||
interface AmountInputProps {
|
||||
value: number;
|
||||
onChange: (valueInCents: number) => void;
|
||||
currencyCode: string;
|
||||
disabled?: boolean;
|
||||
required?: boolean;
|
||||
placeholder?: string;
|
||||
id?: string;
|
||||
}
|
||||
|
||||
const getCurrencySymbol = (currencyCode: string): string => {
|
||||
const symbols: Record<string, string> = {
|
||||
USD: '$',
|
||||
EUR: '€',
|
||||
GBP: '£',
|
||||
JPY: '¥',
|
||||
};
|
||||
return symbols[currencyCode] || currencyCode;
|
||||
};
|
||||
|
||||
export const AmountInput = React.forwardRef<HTMLInputElement, AmountInputProps>(
|
||||
(
|
||||
{
|
||||
value,
|
||||
onChange,
|
||||
currencyCode,
|
||||
disabled = false,
|
||||
required = false,
|
||||
placeholder = '0.00',
|
||||
id,
|
||||
},
|
||||
ref,
|
||||
) => {
|
||||
const [displayValue, setDisplayValue] = React.useState<string>('');
|
||||
|
||||
React.useEffect(() => {
|
||||
if (value === 0) {
|
||||
setDisplayValue('');
|
||||
} else {
|
||||
setDisplayValue((value / 100).toFixed(2));
|
||||
}
|
||||
}, [value]);
|
||||
|
||||
const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
const inputValue = e.target.value;
|
||||
|
||||
if (inputValue === '' || inputValue === '-') {
|
||||
setDisplayValue(inputValue);
|
||||
onChange(0);
|
||||
return;
|
||||
}
|
||||
|
||||
const numericValue = inputValue.replace(/[^\d.-]/g, '');
|
||||
|
||||
if (numericValue === '' || numericValue === '-') {
|
||||
setDisplayValue(numericValue);
|
||||
onChange(0);
|
||||
return;
|
||||
}
|
||||
|
||||
const parsedValue = parseFloat(numericValue);
|
||||
|
||||
if (isNaN(parsedValue)) {
|
||||
return;
|
||||
}
|
||||
|
||||
setDisplayValue(numericValue);
|
||||
|
||||
const valueInCents = Math.round(parsedValue * 100);
|
||||
onChange(valueInCents);
|
||||
};
|
||||
|
||||
const handleBlur = () => {
|
||||
if (displayValue === '' || displayValue === '-') {
|
||||
setDisplayValue('');
|
||||
onChange(0);
|
||||
return;
|
||||
}
|
||||
|
||||
const parsedValue = parseFloat(displayValue);
|
||||
if (!isNaN(parsedValue)) {
|
||||
setDisplayValue(parsedValue.toFixed(2));
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<InputGroup>
|
||||
<InputGroupAddon>
|
||||
<InputGroupText>
|
||||
{getCurrencySymbol(currencyCode)}
|
||||
</InputGroupText>
|
||||
</InputGroupAddon>
|
||||
<InputGroupInput
|
||||
ref={ref}
|
||||
id={id}
|
||||
type="text"
|
||||
inputMode="decimal"
|
||||
value={displayValue}
|
||||
onChange={handleChange}
|
||||
onBlur={handleBlur}
|
||||
placeholder={placeholder}
|
||||
disabled={disabled}
|
||||
required={required}
|
||||
/>
|
||||
<InputGroupAddon align="inline-end">
|
||||
<InputGroupText>{currencyCode}</InputGroupText>
|
||||
</InputGroupAddon>
|
||||
</InputGroup>
|
||||
);
|
||||
},
|
||||
);
|
||||
|
||||
AmountInput.displayName = 'AmountInput';
|
||||
|
||||
|
|
@ -0,0 +1,99 @@
|
|||
import * as React from 'react';
|
||||
|
||||
import { cn } from '@/lib/utils';
|
||||
|
||||
const InputGroup = React.forwardRef<
|
||||
HTMLDivElement,
|
||||
React.HTMLAttributes<HTMLDivElement>
|
||||
>(({ className, ...props }, ref) => {
|
||||
return (
|
||||
<div
|
||||
ref={ref}
|
||||
className={cn(
|
||||
'relative flex w-full items-stretch overflow-hidden rounded-lg border border-input bg-background focus-within:ring-2 focus-within:ring-ring focus-within:ring-offset-2',
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
);
|
||||
});
|
||||
InputGroup.displayName = 'InputGroup';
|
||||
|
||||
const InputGroupAddon = React.forwardRef<
|
||||
HTMLDivElement,
|
||||
React.HTMLAttributes<HTMLDivElement> & {
|
||||
align?: 'inline-start' | 'inline-end' | 'block-end';
|
||||
}
|
||||
>(({ className, align = 'inline-start', ...props }, ref) => {
|
||||
return (
|
||||
<div
|
||||
ref={ref}
|
||||
className={cn(
|
||||
'flex items-center justify-center bg-muted px-3 text-sm text-muted-foreground',
|
||||
align === 'inline-end' && 'order-last',
|
||||
align === 'block-end' && 'order-last w-full border-t',
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
);
|
||||
});
|
||||
InputGroupAddon.displayName = 'InputGroupAddon';
|
||||
|
||||
const InputGroupText = React.forwardRef<
|
||||
HTMLSpanElement,
|
||||
React.HTMLAttributes<HTMLSpanElement>
|
||||
>(({ className, ...props }, ref) => {
|
||||
return (
|
||||
<span
|
||||
ref={ref}
|
||||
className={cn('whitespace-nowrap', className)}
|
||||
{...props}
|
||||
/>
|
||||
);
|
||||
});
|
||||
InputGroupText.displayName = 'InputGroupText';
|
||||
|
||||
const InputGroupInput = React.forwardRef<
|
||||
HTMLInputElement,
|
||||
React.InputHTMLAttributes<HTMLInputElement>
|
||||
>(({ className, type = 'text', ...props }, ref) => {
|
||||
return (
|
||||
<input
|
||||
type={type}
|
||||
className={cn(
|
||||
'flex h-10 w-full flex-1 border-0 bg-transparent px-3 py-2 text-base ring-offset-background file:border-0 file:bg-transparent file:text-sm file:font-medium file:text-foreground placeholder:text-muted-foreground focus-visible:outline-none disabled:cursor-not-allowed disabled:opacity-50 md:text-sm',
|
||||
className,
|
||||
)}
|
||||
ref={ref}
|
||||
{...props}
|
||||
/>
|
||||
);
|
||||
});
|
||||
InputGroupInput.displayName = 'InputGroupInput';
|
||||
|
||||
const InputGroupTextarea = React.forwardRef<
|
||||
HTMLTextAreaElement,
|
||||
React.TextareaHTMLAttributes<HTMLTextAreaElement>
|
||||
>(({ className, ...props }, ref) => {
|
||||
return (
|
||||
<textarea
|
||||
className={cn(
|
||||
'flex min-h-[80px] w-full flex-1 border-0 bg-transparent px-3 py-2 text-base ring-offset-background placeholder:text-muted-foreground focus-visible:outline-none disabled:cursor-not-allowed disabled:opacity-50 md:text-sm',
|
||||
className,
|
||||
)}
|
||||
ref={ref}
|
||||
{...props}
|
||||
/>
|
||||
);
|
||||
});
|
||||
InputGroupTextarea.displayName = 'InputGroupTextarea';
|
||||
|
||||
export {
|
||||
InputGroup,
|
||||
InputGroupAddon,
|
||||
InputGroupInput,
|
||||
InputGroupText,
|
||||
InputGroupTextarea,
|
||||
};
|
||||
|
||||
|
|
@ -516,7 +516,7 @@ export function convertRowsToTransactions(
|
|||
results.push({
|
||||
transaction_date: formattedDate,
|
||||
description,
|
||||
amount,
|
||||
amount: Math.round(amount * 100),
|
||||
balance,
|
||||
validationErrors: [],
|
||||
});
|
||||
|
|
|
|||
|
|
@ -75,7 +75,7 @@ export function prepareTransactionData(
|
|||
|
||||
return {
|
||||
description: normalizeWhitespace((transaction.decryptedDescription || '').toLowerCase()),
|
||||
amount: parseFloat(transaction.amount),
|
||||
amount: transaction.amount / 100,
|
||||
transaction_date: transaction.transaction_date,
|
||||
bank_name: bank?.name || '',
|
||||
account_name: account?.name || '',
|
||||
|
|
|
|||
|
|
@ -396,13 +396,13 @@ export default function Transactions({ categories, accounts, banks }: Props) {
|
|||
|
||||
if (
|
||||
filters.amountMin !== null &&
|
||||
parseFloat(transaction.amount) < filters.amountMin
|
||||
transaction.amount / 100 < filters.amountMin
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
if (
|
||||
filters.amountMax !== null &&
|
||||
parseFloat(transaction.amount) > filters.amountMax
|
||||
transaction.amount / 100 > filters.amountMax
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ export interface Transaction {
|
|||
description: string;
|
||||
description_iv: string;
|
||||
transaction_date: string;
|
||||
amount: string;
|
||||
amount: number;
|
||||
currency_code: string;
|
||||
notes: string | null;
|
||||
notes_iv: string | null;
|
||||
|
|
|
|||
|
|
@ -79,7 +79,7 @@ it('can create a transaction', function () {
|
|||
'description' => 'encrypted_description',
|
||||
'description_iv' => '1234567890123456',
|
||||
'transaction_date' => now()->toDateString(),
|
||||
'amount' => '100.50',
|
||||
'amount' => 10050,
|
||||
'currency_code' => 'USD',
|
||||
'notes' => null,
|
||||
'notes_iv' => null,
|
||||
|
|
@ -109,7 +109,7 @@ it('can create a transaction', function () {
|
|||
'account_id' => $account->id,
|
||||
'category_id' => $category->id,
|
||||
'description' => 'encrypted_description',
|
||||
'amount' => '100.50',
|
||||
'amount' => 10050,
|
||||
]);
|
||||
});
|
||||
|
||||
|
|
@ -125,7 +125,7 @@ it('can create a transaction with a UUID', function () {
|
|||
'description' => 'encrypted_description',
|
||||
'description_iv' => '1234567890123456',
|
||||
'transaction_date' => now()->toDateString(),
|
||||
'amount' => '100.50',
|
||||
'amount' => 10050,
|
||||
'currency_code' => 'USD',
|
||||
'notes' => null,
|
||||
'notes_iv' => null,
|
||||
|
|
@ -155,7 +155,7 @@ it('can update a transaction', function () {
|
|||
$user = User::factory()->create();
|
||||
$account = Account::factory()->for($user)->create();
|
||||
$transaction = Transaction::factory()->for($user)->for($account)->create([
|
||||
'amount' => '100.00',
|
||||
'amount' => 10000,
|
||||
'description' => 'old_description',
|
||||
]);
|
||||
|
||||
|
|
@ -165,7 +165,7 @@ it('can update a transaction', function () {
|
|||
'description' => 'new_description',
|
||||
'description_iv' => $transaction->description_iv,
|
||||
'transaction_date' => $transaction->transaction_date->toDateString(),
|
||||
'amount' => '200.00',
|
||||
'amount' => 20000,
|
||||
'currency_code' => $transaction->currency_code,
|
||||
'notes' => null,
|
||||
'notes_iv' => null,
|
||||
|
|
@ -174,12 +174,12 @@ it('can update a transaction', function () {
|
|||
$response = $this->actingAs($user)->patchJson("/api/sync/transactions/{$transaction->id}", $updateData);
|
||||
|
||||
$response->assertSuccessful()
|
||||
->assertJsonPath('data.amount', '200.00')
|
||||
->assertJsonPath('data.amount', 20000)
|
||||
->assertJsonPath('data.description', 'new_description');
|
||||
|
||||
$this->assertDatabaseHas('transactions', [
|
||||
'id' => $transaction->id,
|
||||
'amount' => '200.00',
|
||||
'amount' => 20000,
|
||||
'description' => 'new_description',
|
||||
]);
|
||||
});
|
||||
|
|
@ -196,7 +196,7 @@ it('cannot update another user transaction', function () {
|
|||
'description' => 'hacked',
|
||||
'description_iv' => $transaction->description_iv,
|
||||
'transaction_date' => $transaction->transaction_date->toDateString(),
|
||||
'amount' => '999.99',
|
||||
'amount' => 99999,
|
||||
'currency_code' => $transaction->currency_code,
|
||||
'notes' => null,
|
||||
'notes_iv' => null,
|
||||
|
|
|
|||
|
|
@ -226,7 +226,7 @@ test('users can create a new transaction', function () {
|
|||
'description' => 'encrypted_description',
|
||||
'description_iv' => str_repeat('d', 16),
|
||||
'transaction_date' => '2025-11-11',
|
||||
'amount' => '150.50',
|
||||
'amount' => 15050,
|
||||
'currency_code' => 'USD',
|
||||
'notes' => 'encrypted_notes',
|
||||
'notes_iv' => str_repeat('n', 16),
|
||||
|
|
@ -258,7 +258,7 @@ test('users can create a new transaction', function () {
|
|||
'account_id' => $account->id,
|
||||
'category_id' => $category->id,
|
||||
'description' => 'encrypted_description',
|
||||
'amount' => '150.50',
|
||||
'amount' => 15050,
|
||||
'currency_code' => 'USD',
|
||||
]);
|
||||
});
|
||||
|
|
@ -273,7 +273,7 @@ test('users can create a transaction without category', function () {
|
|||
'description' => 'encrypted_description',
|
||||
'description_iv' => str_repeat('d', 16),
|
||||
'transaction_date' => '2025-11-11',
|
||||
'amount' => '75.25',
|
||||
'amount' => 7525,
|
||||
'currency_code' => 'EUR',
|
||||
];
|
||||
|
||||
|
|
@ -285,7 +285,7 @@ test('users can create a transaction without category', function () {
|
|||
'account_id' => $account->id,
|
||||
'category_id' => null,
|
||||
'description' => 'encrypted_description',
|
||||
'amount' => '75.25',
|
||||
'amount' => 7525,
|
||||
]);
|
||||
});
|
||||
|
||||
|
|
@ -298,7 +298,7 @@ test('users can create a transaction without notes', function () {
|
|||
'description' => 'encrypted_description',
|
||||
'description_iv' => str_repeat('d', 16),
|
||||
'transaction_date' => '2025-11-11',
|
||||
'amount' => '100.00',
|
||||
'amount' => 10000,
|
||||
'currency_code' => 'USD',
|
||||
];
|
||||
|
||||
|
|
@ -320,7 +320,7 @@ test('account_id is required when creating transaction', function () {
|
|||
'description' => 'encrypted_description',
|
||||
'description_iv' => str_repeat('d', 16),
|
||||
'transaction_date' => '2025-11-11',
|
||||
'amount' => '100.00',
|
||||
'amount' => 10000,
|
||||
'currency_code' => 'USD',
|
||||
];
|
||||
|
||||
|
|
@ -338,7 +338,7 @@ test('description is required when creating transaction', function () {
|
|||
'account_id' => $account->id,
|
||||
'description_iv' => str_repeat('d', 16),
|
||||
'transaction_date' => '2025-11-11',
|
||||
'amount' => '100.00',
|
||||
'amount' => 10000,
|
||||
'currency_code' => 'USD',
|
||||
];
|
||||
|
||||
|
|
@ -374,7 +374,7 @@ test('transaction_date is required when creating transaction', function () {
|
|||
'account_id' => $account->id,
|
||||
'description' => 'encrypted_description',
|
||||
'description_iv' => str_repeat('d', 16),
|
||||
'amount' => '100.00',
|
||||
'amount' => 10000,
|
||||
'currency_code' => 'USD',
|
||||
];
|
||||
|
||||
|
|
@ -393,7 +393,7 @@ test('currency_code is required when creating transaction', function () {
|
|||
'description' => 'encrypted_description',
|
||||
'description_iv' => str_repeat('d', 16),
|
||||
'transaction_date' => '2025-11-11',
|
||||
'amount' => '100.00',
|
||||
'amount' => 10000,
|
||||
];
|
||||
|
||||
$response = actingAs($user)->postJson(route('transactions.store'), $transactionData);
|
||||
|
|
|
|||
Loading…
Reference in New Issue