mirror of
				https://github.com/invoiceninja/invoiceninja.git
				synced 2025-11-04 00:07:35 -05:00 
			
		
		
		
	Use transaction when marking an invoice as paid
This commit is contained in:
		
							parent
							
								
									e961eb58fa
								
							
						
					
					
						commit
						384ce1fa8d
					
				@ -237,6 +237,10 @@ class PaymentEmailEngine extends BaseEmailEngine
 | 
			
		||||
        $data['$invoice.po_number'] = ['value' => $this->formatPoNumber(), 'label' => ctrans('texts.po_number')];
 | 
			
		||||
        $data['$poNumber'] = &$data['$invoice.po_number'];
 | 
			
		||||
        $data['$payment.status'] = ['value' => $this->payment->stringStatus($this->payment->status_id), 'label' => ctrans('texts.payment_status')];
 | 
			
		||||
        $data['$invoices.amount'] = ['value' => $this->formatInvoiceField('amount'), 'label' => ctrans('texts.invoices')];
 | 
			
		||||
        $data['$invoices.balance'] = ['value' => $this->formatInvoiceField('balance'), 'label' => ctrans('texts.invoices')];
 | 
			
		||||
        $data['$invoices.due_date'] = ['value' => $this->formatInvoiceField('due_date'), 'label' => ctrans('texts.invoices')];
 | 
			
		||||
        $data['$invoices.po_number'] = ['value' => $this->formatInvoiceField('po_number'), 'label' => ctrans('texts.invoices')];
 | 
			
		||||
 | 
			
		||||
        $arrKeysLength = array_map('strlen', array_keys($data));
 | 
			
		||||
        array_multisort($arrKeysLength, SORT_DESC, $data);
 | 
			
		||||
@ -244,6 +248,22 @@ class PaymentEmailEngine extends BaseEmailEngine
 | 
			
		||||
        return $data;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private function formatInvoiceField($field)
 | 
			
		||||
    {
 | 
			
		||||
        $invoice = '';
 | 
			
		||||
 | 
			
		||||
        foreach ($this->payment->invoices as $invoice) {
 | 
			
		||||
 | 
			
		||||
            $invoice_field = $invoice->{$field};
 | 
			
		||||
 | 
			
		||||
            $invoice .= ctrans('texts.invoice_number_short') . "{$invoice->number} {$invoice_field}";
 | 
			
		||||
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return $invoice;
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private function formatInvoice()
 | 
			
		||||
    {
 | 
			
		||||
        $invoice = '';
 | 
			
		||||
@ -282,11 +302,15 @@ class PaymentEmailEngine extends BaseEmailEngine
 | 
			
		||||
        $invoice_list = '<br><br>';
 | 
			
		||||
 | 
			
		||||
        foreach ($this->payment->invoices as $invoice) {
 | 
			
		||||
            $invoice_list .= ctrans('texts.po_number')." {$invoice->po_number} <br>";
 | 
			
		||||
            
 | 
			
		||||
            if(strlen($invoice->po_number) > 1)
 | 
			
		||||
                $invoice_list .= ctrans('texts.po_number')." {$invoice->po_number} <br>";
 | 
			
		||||
 | 
			
		||||
            $invoice_list .= ctrans('texts.invoice_number_short')." {$invoice->number} <br>";
 | 
			
		||||
            $invoice_list .= ctrans('texts.invoice_amount').' '.Number::formatMoney($invoice->pivot->amount, $this->client).'<br>';
 | 
			
		||||
            $invoice_list .= ctrans('texts.invoice_balance').' '.Number::formatMoney($invoice->fresh()->balance, $this->client).'<br>';
 | 
			
		||||
            $invoice_list .= '-----<br>';
 | 
			
		||||
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return $invoice_list;
 | 
			
		||||
 | 
			
		||||
@ -41,20 +41,37 @@ class MarkPaid extends AbstractService
 | 
			
		||||
 | 
			
		||||
    public function run()
 | 
			
		||||
    {
 | 
			
		||||
        if ($this->invoice->status_id == Invoice::STATUS_DRAFT) {
 | 
			
		||||
            $this->invoice->service()->markSent()->save();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /*Don't double pay*/
 | 
			
		||||
        if ($this->invoice->status_id == Invoice::STATUS_PAID) {
 | 
			
		||||
            return $this->invoice;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if ($this->invoice->status_id == Invoice::STATUS_DRAFT) {
 | 
			
		||||
            $this->invoice->service()->markSent()->save();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        $payable_balance = $this->invoice->balance;
 | 
			
		||||
 | 
			
		||||
        \DB::connection(config('database.default'))->transaction(function () use($payable_balance) {
 | 
			
		||||
 | 
			
		||||
            $this->invoice = Invoice::where('id', $this->invoice->id)->lockForUpdate()->first();
 | 
			
		||||
 | 
			
		||||
            $this->invoice
 | 
			
		||||
                ->service()
 | 
			
		||||
                ->setExchangeRate()
 | 
			
		||||
                ->updateBalance($payable_balance * -1)
 | 
			
		||||
                ->updatePaidToDate($payable_balance)
 | 
			
		||||
                ->setStatus(Invoice::STATUS_PAID)
 | 
			
		||||
                ->save();
 | 
			
		||||
 | 
			
		||||
        }, 1);
 | 
			
		||||
 | 
			
		||||
        /* Create Payment */
 | 
			
		||||
        $payment = PaymentFactory::create($this->invoice->company_id, $this->invoice->user_id);
 | 
			
		||||
 | 
			
		||||
        $payment->amount = $this->invoice->balance;
 | 
			
		||||
        $payment->applied = $this->invoice->balance;
 | 
			
		||||
        $payment->amount = $payable_balance;
 | 
			
		||||
        $payment->applied = $payable_balance;
 | 
			
		||||
        $payment->status_id = Payment::STATUS_COMPLETED;
 | 
			
		||||
        $payment->client_id = $this->invoice->client_id;
 | 
			
		||||
        $payment->transaction_reference = ctrans('texts.manual_entry');
 | 
			
		||||
@ -79,20 +96,20 @@ class MarkPaid extends AbstractService
 | 
			
		||||
 | 
			
		||||
        /* Create a payment relationship to the invoice entity */
 | 
			
		||||
        $payment->invoices()->attach($this->invoice->id, [
 | 
			
		||||
            'amount' => $payment->amount,
 | 
			
		||||
            'amount' => $payable_balance,
 | 
			
		||||
        ]);
 | 
			
		||||
 | 
			
		||||
        event('eloquent.created: App\Models\Payment', $payment);
 | 
			
		||||
 | 
			
		||||
        $this->invoice->next_send_date = null;
 | 
			
		||||
 | 
			
		||||
        $this->invoice
 | 
			
		||||
                ->service()
 | 
			
		||||
                ->setExchangeRate()
 | 
			
		||||
                ->updateBalance($payment->amount * -1)
 | 
			
		||||
                ->updatePaidToDate($payment->amount)
 | 
			
		||||
                ->setStatus(Invoice::STATUS_PAID)
 | 
			
		||||
                ->save();
 | 
			
		||||
        // $this->invoice
 | 
			
		||||
        //         ->service()
 | 
			
		||||
        //         ->setExchangeRate()
 | 
			
		||||
        //         ->updateBalance($payment->amount * -1)
 | 
			
		||||
        //         ->updatePaidToDate($payment->amount)
 | 
			
		||||
        //         ->setStatus(Invoice::STATUS_PAID)
 | 
			
		||||
        //         ->save();
 | 
			
		||||
 | 
			
		||||
        $this->invoice
 | 
			
		||||
                ->service()
 | 
			
		||||
@ -101,7 +118,7 @@ class MarkPaid extends AbstractService
 | 
			
		||||
                ->save();
 | 
			
		||||
 | 
			
		||||
        $payment->ledger()
 | 
			
		||||
                ->updatePaymentBalance($payment->amount * -1);
 | 
			
		||||
                ->updatePaymentBalance($payable_balance * -1);
 | 
			
		||||
 | 
			
		||||
        \DB::connection(config('database.default'))->transaction(function () use ($payment) {
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -42,9 +42,9 @@ class ZeroCostProduct extends AbstractService
 | 
			
		||||
 | 
			
		||||
        $invoice = $this->subscription->service()->createInvoice($this->data);
 | 
			
		||||
 | 
			
		||||
        $invoice->service()
 | 
			
		||||
                ->markPaid()
 | 
			
		||||
                ->save();
 | 
			
		||||
        $invoice = $invoice->service()
 | 
			
		||||
                           ->markPaid()
 | 
			
		||||
                           ->save();
 | 
			
		||||
 | 
			
		||||
        $redirect_url = "/client/invoices/{$invoice->hashed_id}";
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -72,7 +72,7 @@ class EntityPaidToDateTest extends TestCase
 | 
			
		||||
 | 
			
		||||
        $this->assertEquals($invoice->balance, 20);
 | 
			
		||||
 | 
			
		||||
        $invoice->service()->markPaid()->save();
 | 
			
		||||
        $invoice = $invoice->service()->markPaid()->save();
 | 
			
		||||
 | 
			
		||||
        $this->assertEquals($invoice->paid_to_date, 20);
 | 
			
		||||
    }
 | 
			
		||||
@ -81,7 +81,7 @@ class EntityPaidToDateTest extends TestCase
 | 
			
		||||
    {
 | 
			
		||||
        $invoice = $this->bootNewInvoice();
 | 
			
		||||
 | 
			
		||||
        $invoice->service()->markPaid()->save();
 | 
			
		||||
        $invoice = $invoice->service()->markPaid()->save();
 | 
			
		||||
 | 
			
		||||
        $this->assertEquals(20, $invoice->paid_to_date);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -185,7 +185,7 @@ class InvoiceAmountPaymentTest extends TestCase
 | 
			
		||||
        $this->assertEquals(25, $invoice->balance);
 | 
			
		||||
        $this->assertEquals(25, $invoice->amount);
 | 
			
		||||
 | 
			
		||||
        $invoice->service()->markPaid()->save();
 | 
			
		||||
        $invoice = $invoice->service()->markPaid()->save();
 | 
			
		||||
 | 
			
		||||
        $invoice->fresh();
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -1422,7 +1422,7 @@ class PaymentTest extends TestCase
 | 
			
		||||
        $this->assertEquals(10, $this->invoice->balance);
 | 
			
		||||
        $this->assertEquals(10, $this->invoice->client->fresh()->balance);
 | 
			
		||||
 | 
			
		||||
        $this->invoice->service()->markPaid()->save();
 | 
			
		||||
        $this->invoice = $this->invoice->service()->markPaid()->save();
 | 
			
		||||
 | 
			
		||||
        $this->assertEquals(0, $this->invoice->balance);
 | 
			
		||||
        $this->assertEquals(0, $this->invoice->client->balance);
 | 
			
		||||
 | 
			
		||||
@ -40,7 +40,7 @@ class GoogleAnalyticsTest extends TestCase
 | 
			
		||||
        $invoice = $this->invoice;
 | 
			
		||||
        $client = $this->client;
 | 
			
		||||
 | 
			
		||||
        $invoice->service()->markPaid()->save();
 | 
			
		||||
        $invoice = $invoice->service()->markPaid()->save();
 | 
			
		||||
 | 
			
		||||
        $payment = $invoice->payments->first();
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -45,7 +45,7 @@ class InvoiceActionsTest extends TestCase
 | 
			
		||||
    {
 | 
			
		||||
        $this->withoutEvents();
 | 
			
		||||
 | 
			
		||||
        $this->invoice->service()->markPaid()->save();
 | 
			
		||||
        $this->invoice = $this->invoice->service()->markPaid()->save();
 | 
			
		||||
 | 
			
		||||
        $this->assertFalse($this->invoiceDeletable($this->invoice));
 | 
			
		||||
        $this->assertTrue($this->invoiceReversable($this->invoice));
 | 
			
		||||
 | 
			
		||||
@ -82,7 +82,7 @@ class SubscriptionsCalcTest extends TestCase
 | 
			
		||||
 | 
			
		||||
        $this->assertFalse($sub_calculator->isPaidUp());
 | 
			
		||||
 | 
			
		||||
        $invoice->service()->markPaid()->save();
 | 
			
		||||
        $invoice = $invoice->service()->markPaid()->save();
 | 
			
		||||
 | 
			
		||||
        $this->assertTrue($sub_calculator->isPaidUp());
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user