Compare commits

...

734 Commits

Author SHA1 Message Date
David Bomba
0a6c7e44dc
Merge pull request #10022 from turbo124/v5-develop
v5.10.29
2024-09-20 10:09:15 +10:00
David Bomba
53d92a67a9 Updated version 2024-09-20 10:08:37 +10:00
David Bomba
752324cced
Merge pull request #10021 from turbo124/v5-develop
Updated translations
2024-09-20 08:45:49 +10:00
David Bomba
92ba61be51 QB imports 2024-09-19 20:12:56 +10:00
David Bomba
6afd7a8970 Fixes for quickbooks sync 2024-09-19 16:44:30 +10:00
David Bomba
1fd186e1ec Fixes for quickbooks sync 2024-09-19 16:39:53 +10:00
David Bomba
23ad59967e minor fixes 2024-09-19 15:00:58 +10:00
David Bomba
eebf72d042 Handle purchase order previews from designer 2024-09-19 14:47:51 +10:00
David Bomba
9977f2c47e Minor fixes 2024-09-19 13:48:02 +10:00
David Bomba
5731763071 Fixes for previews 2024-09-19 13:38:03 +10:00
David Bomba
4daa321ecf Fixes for converting expired quotes 2024-09-19 11:05:31 +10:00
David Bomba
79ef8aea18 Updated translations 2024-09-19 10:56:44 +10:00
David Bomba
2aba873d16 remove blockonomics payment type 2024-09-19 09:55:03 +10:00
David Bomba
6f644f3070
Merge pull request #10012 from turbo124/v5-develop
Add back blockonomics
2024-09-19 09:45:58 +10:00
David Bomba
8dffba42d6 Refactor blockonomics JS for one page checkout 2024-09-19 09:45:08 +10:00
David Bomba
a675dd685a Updated resources 2024-09-19 08:18:25 +10:00
David Bomba
19cf39786e Fixes for blockonomics 2024-09-19 08:17:51 +10:00
David Bomba
ba6a63c63e
Merge pull request #10004 from beganovich/1533-powerboard
PowerBoard: Refocus card widget on failure
2024-09-18 16:00:08 +10:00
Benjamin Beganović
2d316d439d assets build 2024-09-17 13:27:00 +02:00
Benjamin Beganović
196d785f19 toggle credit card view after resetting the widget 2024-09-17 13:26:47 +02:00
David Bomba
984a8666aa
Merge pull request #10001 from turbo124/v5-develop
Powerboard payment driver
2024-09-17 10:44:41 +10:00
David Bomba
ee637b2555 Resources 2024-09-17 10:44:25 +10:00
David Bomba
20b04a266f merge 2024-09-17 10:17:07 +10:00
David Bomba
114b58cdc4
Beganovich 1513 powerboard (#103)
* make container nicer

* assets rebuild

* authorize powerband card (3ds)

* add reference to build file

* update authorize (3ds) view

* assets rebuild

* unify 3ds and non-3ds auth/pay

* assets rebuild

* authorize

* pay

* update vite refs

* pay

* hide authorize button

* intercepting form on authorize

* assets build

* wip

* init powerboard in data ref

* fixes for blank placeholders

* reset the form on failed 3ds

* handling unsuccessful errors

* send email on payment failed

* fixes for 3ds fail on auth

* assets rebuild

* make card_name required

* make card_name required (on auth)

* fixes for blocked pay-now button

* fixes for reload

* fixes for reload

* build

* Fixes for broken powerboard

* make client name required

* skip fields checking if no required fields

* on request, return json response

* check for plain not_authenticated response

* flash message when no action is present

* fixes for exec order on token

* assets build

* check for plain not_authenticated response (pay)

* assets build

* adjustments for minimum payments

* Add text decoration to terms button

* Improvements for subscriptions and new payment flow

---------

Co-authored-by: Benjamin Beganović <k1pstabug@gmail.com>
2024-09-17 10:16:10 +10:00
David Bomba
b1d92d8354 Merge branch 'powerboard' into v5-develop 2024-09-17 10:09:53 +10:00
David Bomba
715a9f34a6 Add migrations 2024-09-17 10:06:11 +10:00
Benjamin Beganović
abe8bbcd5d
Refactor PowerBoard (#102)
* make container nicer

* assets rebuild

* authorize powerband card (3ds)

* add reference to build file

* update authorize (3ds) view

* assets rebuild

* unify 3ds and non-3ds auth/pay

* assets rebuild

* authorize

* pay

* update vite refs

* pay

* hide authorize button

* intercepting form on authorize

* assets build

* wip

* init powerboard in data ref

* fixes for blank placeholders

* reset the form on failed 3ds

* handling unsuccessful errors

* send email on payment failed

* fixes for 3ds fail on auth

* assets rebuild

* make card_name required

* make card_name required (on auth)

* fixes for blocked pay-now button

* fixes for reload

* fixes for reload

* build

* make client name required

* skip fields checking if no required fields

* on request, return json response

* check for plain not_authenticated response

* flash message when no action is present

* fixes for exec order on token

* assets build

* check for plain not_authenticated response (pay)

* assets build
2024-09-17 10:05:19 +10:00
David Bomba
b1f1eb0ccd Fixes for tests 2024-09-17 07:21:12 +10:00
David Bomba
c9db1688fd Remove annotations from tests 2024-09-17 07:02:30 +10:00
David Bomba
1a438ecd64 Remove annotations from tests 2024-09-16 21:13:55 +10:00
David Bomba
56cbc3f58b Fixes for php unit 2024-09-16 21:12:47 +10:00
David Bomba
6a7dd0351b phpunit 11 fixes 2024-09-16 20:42:02 +10:00
David Bomba
cf28dffab8 Process Isolation 2024-09-16 20:09:56 +10:00
David Bomba
0c79897987 Update to phpunit 11 2024-09-16 20:06:23 +10:00
David Bomba
77b5e220c6 Update .env.example vars 2024-09-16 19:54:06 +10:00
David Bomba
c94fc8a6da Update .env.example vars 2024-09-16 19:44:22 +10:00
David Bomba
ab9b96d7f2 Update .env.example vars 2024-09-16 18:52:44 +10:00
David Bomba
15ed82e5b2 Update .env.example vars 2024-09-16 18:37:53 +10:00
David Bomba
818e47adff Update .env.example vars 2024-09-16 18:37:27 +10:00
David Bomba
a9e3533647
Merge pull request #9996 from turbo124/v5-develop
Roll back for PHP 8.3 tests
2024-09-16 16:58:59 +10:00
David Bomba
a2f371e814 Roll back for PHP 8.3 tests 2024-09-16 16:58:40 +10:00
David Bomba
6d67333431
Merge pull request #9995 from turbo124/v5-develop
Updated lock
2024-09-16 16:57:42 +10:00
David Bomba
36b5a595f1 Updated lock 2024-09-16 16:57:24 +10:00
David Bomba
cdacdc851e
Merge pull request #9042 from paulwer/feature-inbound-email-expenses
Feature: inbound email expenses & mindee ocr
2024-09-16 16:56:05 +10:00
David Bomba
40ebad7dca
Merge branch 'v5-develop' into feature-inbound-email-expenses
Signed-off-by: David Bomba <turbo124@gmail.com>
2024-09-16 16:55:52 +10:00
David Bomba
209d335df5
Merge pull request #9994 from turbo124/v5-develop
New payment flow + einvoicing fixes
2024-09-16 16:53:42 +10:00
David Bomba
f8698c0270
Merge branch 'v5-develop' into v5-develop
Signed-off-by: David Bomba <turbo124@gmail.com>
2024-09-16 16:53:34 +10:00
David Bomba
db7c21e761 Fixes for expense engine 2024-09-16 16:47:57 +10:00
David Bomba
ff695cdad0 improve validation 2024-09-16 15:59:39 +10:00
paulwer
3f0f5663a9 fix: mindee taxation transform issue 2024-09-16 06:57:02 +02:00
David Bomba
0c61555739 Additional props for einvoicing 2024-09-16 14:04:22 +10:00
David Bomba
9c6568aae1 Split einvoice gateways 2024-09-16 13:52:46 +10:00
David Bomba
bfbf7f5c6a Split einvoice gateways 2024-09-16 13:35:23 +10:00
David Bomba
737e18aa42 Split einvoice gateways 2024-09-16 13:12:46 +10:00
David Bomba
50faf3261b qvalia 2024-09-16 11:50:19 +10:00
David Bomba
fb46889bb4 qvalia 2024-09-16 10:59:23 +10:00
David Bomba
6f25be937d Qvalias 2024-09-16 10:52:12 +10:00
David Bomba
2221353622 Add duplicate request checks on bulk invoice actions 2024-09-16 10:06:34 +10:00
David Bomba
5c0f228cb7 Updates 2024-09-15 18:54:48 +10:00
David Bomba
10f6977023 Adjustments for expense imports 2024-09-15 17:32:43 +10:00
paulwer
3aa17bd6cd remove mimes validation within edocument endpoint, because ParseEDocument handles this + minor code cleanups 2024-09-15 08:18:07 +02:00
paulwer
9ced189262 Merge branch 'v5-develop' of https://github.com/invoiceninja/invoiceninja into feature-inbound-email-expenses 2024-09-15 07:42:43 +02:00
David Bomba
812bc91947 Updates for PEPPOL 2024-09-15 14:40:52 +10:00
David Bomba
c77da63b62 Fixes for es-* migrations 2024-09-15 13:28:39 +10:00
David Bomba
37f28d8a31 Add 3 autonomous regions of spain 2024-09-15 13:24:06 +10:00
David Bomba
506f7b5d7a Add 3 autonomous regions of spain 2024-09-15 13:23:49 +10:00
David Bomba
02d93356aa Add 3 autonomous regions of spain 2024-09-15 12:35:27 +10:00
David Bomba
c812be495c Fixes for passinig institution ID for nordigen 2024-09-15 11:01:31 +10:00
David Bomba
d93e3a77b3 Add tax type for PEPPOL 2024-09-14 19:16:54 +10:00
David Bomba
50f0f7d3ec
Merge pull request #9988 from arnebr/patch-einvoice
E-Invoice: Payment means code can only contain  credit transfer codes
2024-09-14 07:24:33 +10:00
Arne Breitsprecher
7892c6554d
Merge branch 'v5-develop' into patch-einvoice
Signed-off-by: Arne Breitsprecher <arnebr@gmail.com>
2024-09-13 15:30:24 +02:00
Arne Breitsprecher
6c83ccc1dd
E-Invoice: Payment means type codecontains a code for credit transfer only 30, 58 are allowd 2024-09-13 15:25:39 +02:00
David Bomba
fc3ca1c124 Add back e_invoice logic 2024-09-11 16:38:12 +10:00
David Bomba
f11f204792 Updated translations 2024-09-11 15:24:19 +10:00
David Bomba
730d55a31e Update the documentation relating to how we assemble custom fields on the company object 2024-09-11 11:31:26 +10:00
David Bomba
3703ec1b36 Updated openapi spec 2024-09-11 11:18:09 +10:00
Benjamin Beganović
0c22f9b27a
Redirect to authorization when token is not available (#100)
* gocardless: sepa

* gocardless: direct debit

* braintree ach (wip)

* braintree: ach

* rotessa: ach
2024-09-11 07:37:12 +10:00
David Bomba
a55155f1fb Updates for twig 2024-09-10 18:39:43 +10:00
David Bomba
c87f25cc72 3ds 2024-09-10 16:42:59 +10:00
David Bomba
ca187bb1da 3ds 2024-09-10 16:42:10 +10:00
David Bomba
2a890fe6f8 Pass bank trashed transactions 2024-09-10 16:36:49 +10:00
David Bomba
eea3f396c6 add logging 2024-09-10 16:36:20 +10:00
David Bomba
ec5b4243a2 Update logic 2024-09-10 16:04:10 +10:00
David Bomba
3d67fe327b Update logic 2024-09-10 15:43:05 +10:00
David Bomba
e08fcbaf07 only show active transactions 2024-09-10 15:40:17 +10:00
David Bomba
305e3daeb4 Minor fixes 2024-09-10 14:47:29 +10:00
David Bomba
4d72a312d6 Fixes for statements 2024-09-10 14:29:01 +10:00
David Bomba
953a8b632b Additional error handlers 2024-09-10 13:51:43 +10:00
David Bomba
69c166c3e9 minor fixes 2024-09-10 12:15:48 +10:00
David Bomba
0c8e5b2e37 Pay Now using ninja tokens 2024-09-10 12:07:50 +10:00
David Bomba
53e295df4c Refactor for self hosted pay now button 2024-09-10 11:50:15 +10:00
David Bomba
4f46fa1029 Testing powerboard 2024-09-10 09:49:17 +10:00
David Bomba
b715c7dd20 powerboardOM 2024-09-10 08:40:40 +10:00
David Bomba
6177483791 Authorize 2024-09-09 19:56:47 +10:00
David Bomba
1172e4bfc1 Authorize.blade.php 2024-09-09 19:36:25 +10:00
David Bomba
d2d807dd7d Powerboard 2024-09-09 19:02:25 +10:00
David Bomba
3689931624 powerboard 2024-09-09 18:50:07 +10:00
David Bomba
0e070ed5c1 powerboard 3ds flow completion 2024-09-09 18:19:29 +10:00
hillelcoren
b568f09da2 Admin Portal - Selfhosted 2024-09-09 06:53:01 +00:00
hillelcoren
0d495041e7 Admin Portal - Profile 2024-09-09 06:46:41 +00:00
hillelcoren
c4f11fcc7f Admin Portal - Hosted 2024-09-09 06:40:28 +00:00
David Bomba
54afae4d8b Exception handling 2024-09-09 16:28:56 +10:00
David Bomba
2e114692e7 3ds payment flow 2024-09-09 15:52:11 +10:00
David Bomba
2c6c7cc3b8 Open API docs 2024-09-09 14:26:06 +10:00
David Bomba
ae73f0aa0d Updates for cleaning stale fees 2024-09-09 10:45:30 +10:00
hillelcoren
03bb4877e2 Admin Portal - Selfhosted 2024-09-08 18:53:39 +00:00
hillelcoren
c8af154288 Admin Portal - Profile 2024-09-08 18:47:31 +00:00
hillelcoren
c1fc4ad358 Admin Portal - Hosted 2024-09-08 18:41:25 +00:00
David Bomba
590616a780 Payment with 3ds 2024-09-08 19:52:39 +10:00
David Bomba
1f3c37a76b powerboard 2024-09-08 19:06:31 +10:00
hillelcoren
b7de04de0d Admin Portal - Selfhosted 2024-09-08 08:06:10 +00:00
hillelcoren
c27d8acc9a Admin Portal - Profile 2024-09-08 08:00:02 +00:00
hillelcoren
7142f1e51a Admin Portal - Hosted 2024-09-08 07:53:59 +00:00
hillelcoren
db8bafac3c Admin Portal - Hosted 2024-09-08 07:50:23 +00:00
David Bomba
a9aa6aea87 Customers model: 2024-09-07 17:32:23 +10:00
David Bomba
e721351a4b Symfony Serializer 2024-09-07 17:28:48 +10:00
David Bomba
c0483d727f Symfony Serializer 2024-09-07 17:27:00 +10:00
David Bomba
78367c1e2d Add payment method and attach to customer 2024-09-07 16:37:20 +10:00
David Bomba
a5317ff093 Remove redundant code path 2024-09-07 15:17:36 +10:00
David Bomba
587159c8c0 Taxes with add back gateway fees 2024-09-07 11:21:05 +10:00
David Bomba
1c855b42d5 Taxes with add back gateway fees 2024-09-07 11:17:44 +10:00
David Bomba
3c226a524c Fixes for gateway fees 2024-09-07 09:52:52 +10:00
David Bomba
9053e6ac7e powerboard 2024-09-07 09:52:35 +10:00
David Bomba
6d2638c603 powerboard 2024-09-07 09:34:53 +10:00
David Bomba
67407103c7 Powerboard 2024-09-06 23:14:21 +10:00
David Bomba
734878a73d powerboard 2024-09-06 22:55:56 +10:00
David Bomba
6876a647ca powerboard 2024-09-06 19:15:08 +10:00
David Bomba
454f7df01e Powerboard 2024-09-06 18:31:00 +10:00
David Bomba
54c1831228 Powerboard 2024-09-06 15:15:33 +10:00
David Bomba
30ff490977 powerboard 2024-09-06 14:34:54 +10:00
David Bomba
3de9c99d34 powerboard 2024-09-06 14:26:13 +10:00
David Bomba
9c8afcd434 Allow invoice PDFs to download via interface 2024-09-06 13:58:39 +10:00
David Bomba
6a5b559983 Fixes for OTP 2024-09-06 11:04:19 +10:00
David Bomba
43b2bef464 Cleaner error handling for gateway errors 2024-09-06 09:40:42 +10:00
David Bomba
0017307e39 Minor fixes for PayPalOM 2024-09-06 08:54:26 +10:00
David Bomba
7444355dee Fixes for first selction on Radio Buttons 2024-09-06 08:17:03 +10:00
Benjamin Beganović
1d45a3944b
fixes for becs (#99) 2024-09-06 07:33:09 +10:00
Benjamin Beganović
3a609f19b1
Stripe BACS: Preselect payment method (#98)
* preselect first method for bacs

* assets rebuild
2024-09-06 07:32:50 +10:00
Benjamin Beganović
b4ee01cc60
Fixes for Stripe ACSS (#97)
* fixes for post-auth redirect on acss

* preselect first acss account

* clean up
2024-09-06 07:32:34 +10:00
David Bomba
ee399ae30b
Merge pull request #9971 from heddn/php83
Update PHP 8.3 in test runner
2024-09-06 07:23:56 +10:00
David Bomba
de87b03952 Minor fixes for invoice summaryu 2024-09-05 21:23:40 +10:00
David Bomba
7bf7ae1d31 Fixes for instant bank payment 2024-09-05 19:41:21 +10:00
David Bomba
2082d2bf8a updates for Forte 2024-09-05 19:05:37 +10:00
David Bomba
31da9cf5ab updates for Forte 2024-09-05 19:04:40 +10:00
David Bomba
59ba737f5d Fixes for redirect URL when client portal is disabled 2024-09-05 16:08:09 +10:00
David Bomba
45553416de Fixes for flow2 2024-09-05 15:55:14 +10:00
David Bomba
63f3115a02 Error handling in livewire 2024-09-05 15:06:21 +10:00
David Bomba
076f168707 Working on payment flows 2024-09-05 13:57:03 +10:00
David Bomba
c74fac68f4 Fixes for disabled client portal payments 2024-09-05 13:22:55 +10:00
David Bomba
500f289647 Add ACSS or USD option for ACSS transfers 2024-09-05 11:55:47 +10:00
David Bomba
5b290a99b4 Merge new payment flow v2 2024-09-05 11:34:29 +10:00
David Bomba
b05e58beb9 Minor annotations for Stripe SEPA 2024-09-05 10:51:32 +10:00
David Bomba
59bcd30b77 Minor annotations for Stripe SEPA 2024-09-05 10:50:36 +10:00
Benjamin Beganović
8268dc332b Braintree: Show loader on PayPal when redirecting (#96)
* add spinner

* show spinner on successful run

* assets rebuild
2024-09-04 18:36:45 +02:00
Benjamin Beganović
dfd12adb56 Authorize.net: Upgrade authorize to use Simple Card (#95)
* update authorize view

* update js

* assets rebuild
2024-09-04 18:36:32 +02:00
David Bomba
57f1eebb30 Fixes for namespace 2024-09-04 18:36:20 +02:00
Benjamin Beganović
babd4580d2 New payment flow: Masking with blank space (#94)
* bump simple card to .4

* update authorize

* update forte

* assets build
2024-09-04 18:36:07 +02:00
David Bomba
b4d1504c9b Fixes for required fields for paytrace 2024-09-04 18:35:54 +02:00
Benjamin Beganović
236c55de33 Paytrace: Add loaders (#93)
* nullable access payment hash data

* add loaders to js

* add loaders to authorize

* assets build
2024-09-04 18:35:32 +02:00
Benjamin Beganović
eb914df7ac Forte: Refactor authorization (#90)
* include sc in pay

* refactor authorize

* include sc in pay livewire
2024-09-04 18:35:26 +02:00
Benjamin Beganović
1add1b392f New payment flow. Fixes for meta ref (#92)
* authorize

* eway

* bacs

* becs

* credit card

* przelewy24
2024-09-04 18:35:19 +02:00
Benjamin Beganović
c341dfd3cd Eway: Add loaders (#91)
* eway: add loaders

* assets build
2024-09-04 18:35:06 +02:00
Benjamin Beganović
414cfca1af New payment flow: Various fixes (#89)
* assets builds

* authorize: use simple-card from asset

* forte: use simple-card from asset

* remove @invoiceninja/simple-card from package

* update usages

* stripe: ach fix

* stripe: alipay fix

* stripe: bacs fix

* stripe: acss fix

* stripe: giropay fix

* assets build
2024-09-04 18:34:59 +02:00
Benjamin Beganović
65491a6e5e New payment flow: Various fixes (#88)
* checkout: fixes for view

* alipay: fixes for method implementation

* checkout: fixes for instant payments

* livewire: revert back the local patch

* remove livewire local patch
2024-09-04 18:34:35 +02:00
Benjamin Beganović
f6333fcae0 Fixes for CVV issues on Authorize & Forte (#84)
* fixes for forte

* fixes for authorize
2024-09-04 18:34:15 +02:00
Benjamin Beganović
0e8da70f77 Apply Livewire patch to load assets async (#85)
* apply livewire local patch

* assets build

* remove manual chunking

* assets build
2024-09-04 18:34:10 +02:00
David Bomba
f45c476d5b Fixes for pp cc 2024-09-04 18:33:54 +02:00
Benjamin Beganović
3b9f1e55fd Fixes for Forte & Authorize.net (#83)
* configure manual chunks for forte & authorize

* assets build
2024-09-04 18:32:49 +02:00
Benjamin Beganović
f564e7529d PayPal: New payment flow (#81)
* extract payment view and data

* scaffold pay livewire

* express

* fix for checkout interface

* card

* rest

* ppcp

* assets build

* fix for duplicate pay button
2024-09-04 18:31:47 +02:00
David Bomba
b4810434c2 Updates for multi invoice payment flow 2024-09-04 18:29:23 +02:00
David Bomba
c01bc9bda8 Updates for payment flow 2024-09-04 18:28:05 +02:00
David Bomba
1f2bb6adf7 Improve new flow 2024-09-04 18:27:51 +02:00
Benjamin Beganović
cacd3e0790 New payment flow: Refactor base driver (#70)
* pass livewirePaymentView & processPaymentView thru base driver

* add paymentData to the interface
2024-09-04 18:27:08 +02:00
Benjamin Beganović
83ced6d340 GoCardless: New payment flow (#72)
* pass livewirePaymentView & processPaymentView thru base driver

* gocardless
2024-09-04 18:26:26 +02:00
Benjamin Beganović
8fbd8a9593 Mollie: New payment flow (#73)
* pass livewirePaymentView & processPaymentView thru base driver

* add paymentData to the interface

* mollie

* credit card
2024-09-04 18:26:22 +02:00
Benjamin Beganović
d68b75641a BTCPay: New payment flow (#76)
* pass livewirePaymentView & processPaymentView thru base driver

* add paymentData to the interface

* btcpay
2024-09-04 18:26:15 +02:00
Benjamin Beganović
49d96e57bb Braintree: New payment flow (#77)
* pass livewirePaymentView & processPaymentView thru base driver

* add paymentData to the interface

* braintree
2024-09-04 18:26:10 +02:00
Benjamin Beganović
fc80287429 Paytrace: New payment flow (#74)
* pass livewirePaymentView & processPaymentView thru base driver

* add paymentData to the interface

* paytrace
2024-09-04 18:25:24 +02:00
Benjamin Beganović
cbd852a0fc Payfast: New payment flow (#78)
* pass livewirePaymentView & processPaymentView thru base driver

* add paymentData to the interface

* payfast
2024-09-04 18:25:17 +02:00
Benjamin Beganović
503e95a691 Razorpay: New payment flow (#79)
* pass livewirePaymentView & processPaymentView thru base driver

* add paymentData to the interface

* razorpay
2024-09-04 18:25:10 +02:00
Benjamin Beganović
5a5abdaeed update instant payment refs (#80) 2024-09-04 18:25:01 +02:00
Benjamin Beganović
eb1576aa7c Square: New payment flow (#75)
* pass livewirePaymentView & processPaymentView thru base driver

* square
2024-09-04 18:24:53 +02:00
Benjamin Beganović
339a92fa6f eway (#69) 2024-09-04 18:24:46 +02:00
Benjamin Beganović
e7f41c1dba Authorize.net: New payment flow (#68)
* fixes for validation errors

* authorize.net

* pass livewirePaymentView & processPaymentView thru base driver

* add paymentData to the interface

* authorize.net credit card
2024-09-04 18:24:34 +02:00
Benjamin Beganović
364a57c857 Stripe: New payment flow (#67)
* stripe: ach

* stripe: klarna

* stripe: bank transfer

* assets build

* stripe: bacs

* stripe: bancontact

* stripe: becs

* stripe: eps

* stripe: fpx

* stripe: giropay

* stripe: ideal

* stripe: przelewy24

* stripe: sepa

* stripe: sofort

* assets build

* assets build

* pass context payload into livewirePaymentView

* update checkout.com

* update livewire method interface

* stripe: acss

* align methods with interface (array $data)
2024-09-04 18:24:05 +02:00
Benjamin Beganović
a4592d666b Refactor context passing between methods and Livewire (#65)
* checkout.com credit card payment for livewire

* implement interface for livewire view

* livewire method interface

* implement interfaces

* assets production build

* checkout.com: credit card

* stripe: credit card

* lift up logic from process payment component

* update stripe payment view logic

* wait fn for mounting existing JS

* credit card: simplify data passing

* stripe: browser pay

* stripe cc: remove getData

* stripe: cc

* stripe: alipay

* checkout :cc

* stripe: apple pay

* stripe: browser pay

* assets production build
2024-09-04 18:22:14 +02:00
Benjamin Beganović
8d4ab0cd69 New payment flow (#64)
* remove context from invoice-pay

* withsecurecontext trait

* update usages

* wip

* wip

* wip

* wip

* wip
2024-09-04 17:41:39 +02:00
David Bomba
e70de19c9d Required fields 2024-09-04 17:37:27 +02:00
David Bomba
78f79a341e improvements for validation of over/under payments 2024-09-04 17:36:58 +02:00
David Bomba
0605154d73 Working on integrating multiple invoice payments 2024-09-04 17:34:27 +02:00
David Bomba
96a3599b7e improvements for validation of over/under payments 2024-09-04 17:31:29 +02:00
David Bomba
6983104f40 Improvements fo reactivity 2024-09-04 17:31:04 +02:00
David Bomba
ae2bf51028 new payment flow 2024-09-04 17:29:41 +02:00
David Bomba
caeed4456b Improve spinners between loads 2024-09-04 17:26:26 +02:00
David Bomba
157841da9b Updates for new payment flow 2024-09-04 17:25:25 +02:00
David Bomba
5aede4e36f Updates for new payment flow 2024-09-04 17:24:24 +02:00
David Bomba
f242bddcb4 Updates for payment flow 2024-09-04 17:24:15 +02:00
David Bomba
9b24eb5f94 working on payment flow 2024-09-04 17:24:04 +02:00
David Bomba
621cd1e169 updates for html invoice layout 2024-09-04 17:23:56 +02:00
David Bomba
a47040aa15 Updated - now trying to get vite and livewire to play nice 2024-09-04 17:21:23 +02:00
David Bomba
cfe04bfa7c Add new entry point for livewire component payments 2024-09-04 17:03:48 +02:00
David Bomba
985cdafdc2 Updated flow 2024-09-04 17:01:01 +02:00
David Bomba
76f6c51a1b Payment methods 2024-09-04 16:58:02 +02:00
David Bomba
c7d6b50778 Payment float 2024-09-04 16:57:38 +02:00
David Bomba
0f27b8474c New payment flow 2024-09-04 16:57:06 +02:00
Lucas D Hedding
72009d2269
Merge remote-tracking branch 'origin/v5-develop' into HEAD 2024-09-04 08:47:35 -06:00
Lucas D Hedding
f9465b6288
attempt to fix failing test 2024-09-04 08:43:56 -06:00
David Bomba
6d356293c1 assets 2024-09-04 17:40:33 +10:00
David Bomba
3adbbea28c Add back wait js 2024-09-04 17:39:02 +10:00
David Bomba
492577f9db minor fixeS 2024-09-04 17:36:26 +10:00
David Bomba
72c818bed0 Push back flow2 js changes 2024-09-04 17:30:53 +10:00
David Bomba
690ed95c9a Fixes for Stripe 2024-09-04 15:57:36 +10:00
David Bomba
35c79dbc50 Fixes for new payment flow 2024-09-04 13:50:37 +10:00
David Bomba
cba76cd608 Add back interface methods for new payment flows 2024-09-04 13:48:23 +10:00
David Bomba
4e59f4d8a8 Fixes for new payment flow 2024-09-04 13:36:50 +10:00
David Bomba
bca672a1fb Fixes for new payment flow 2024-09-04 13:20:40 +10:00
David Bomba
d11dcc27b7 Updated assets 2024-09-04 13:01:32 +10:00
David Bomba
c6d5676d3e Merge new payment flow 2024-09-04 13:00:04 +10:00
David Bomba
9b2d745bcf Updates to allow pink auto billing 2024-09-04 12:26:35 +10:00
David Bomba
e1ec2928a9 Fixes for tests 2024-09-04 10:10:08 +10:00
David Bomba
bd406136d6 Tests for new clean fee items method 2024-09-04 09:24:32 +10:00
David Bomba
c71d7ffeec Ensure line item gateway fees are not cloned 2024-09-04 09:17:46 +10:00
David Bomba
e491231090 Fixes for tests 2024-09-04 08:13:53 +10:00
Lucas D Hedding
5b9af52ba1
fix failing tests, resolves https://github.com/laravel/framework/issues/49237 2024-09-03 09:32:29 -06:00
David Bomba
12efe721d1 Fixes for tests 2024-09-03 18:20:00 +10:00
David Bomba
f893a75e9b Validate e-invoice payload 2024-09-03 16:36:46 +10:00
David Bomba
607f2ff69c Tests for entity validation for einvoicing 2024-09-03 15:36:01 +10:00
David Bomba
26d55d112d Performs a validation check at the entity level 2024-09-03 13:42:22 +10:00
David Bomba
bff5b627fd Set most recent payment method as default 2024-09-03 12:57:41 +10:00
David Bomba
0138d8d246 Set most recent payment method as default 2024-09-03 11:48:31 +10:00
David Bomba
c2121a051d Remove PHP 8.3 from test runners 2024-09-03 10:40:57 +10:00
David Bomba
93be683995 Tests 2024-09-03 10:40:34 +10:00
David Bomba
792d982f03 Silence company user test 2024-09-03 09:55:20 +10:00
David Bomba
5319bbe653 Fixes 2024-09-03 09:54:44 +10:00
David Bomba
40b209f8e0 Fixes 2024-09-03 09:50:16 +10:00
David Bomba
fa7ce1bc24 Fixes for tests 2024-09-03 09:49:29 +10:00
David Bomba
2fd861d65c Fixes for tests 2024-09-03 09:41:38 +10:00
David Bomba
f4bea090a8 Fixes for tests 2024-09-03 09:40:13 +10:00
David Bomba
73c09d30e3 Fixes for tests 2024-09-03 09:37:09 +10:00
David Bomba
9acced72e1 Fixes for tests 2024-09-03 09:34:39 +10:00
David Bomba
4a74adb178 Add back process isolation 2024-09-03 09:30:31 +10:00
David Bomba
777c3d5d66 Fixes for tests 2024-09-03 09:27:25 +10:00
David Bomba
fe2dbebdf5 Add support for PHP 8.3 tests 2024-09-03 09:26:58 +10:00
David Bomba
aa036c6e40 Add support for PHP 8.3 tests 2024-09-03 09:06:39 +10:00
David Bomba
f85e96c3a6 Updates for e-invoicing 2024-09-03 09:02:46 +10:00
David Bomba
8b8a5e3148 remove process isolation for PHP 8.3 tests 2024-09-03 08:35:13 +10:00
David Bomba
b37dfe63e9 Add back php 8.3 into test runner 2024-09-03 08:21:18 +10:00
David Bomba
a45dcc5580 Fixes for tests 2024-09-03 08:20:32 +10:00
Lucas Hedding
4f22fb9812
Update phpunit.yml
Signed-off-by: Lucas Hedding <heddn@users.noreply.github.com>
2024-09-02 16:17:13 -06:00
David Bomba
ada65c8da9 Move e_invoice null filter into form request 2024-09-03 07:58:37 +10:00
Benjamin Beganović
6c0b451c23
Braintree: Show loader on PayPal when redirecting (#96)
* add spinner

* show spinner on successful run

* assets rebuild
2024-09-03 07:03:28 +10:00
Benjamin Beganović
0695e5bfc1
Authorize.net: Upgrade authorize to use Simple Card (#95)
* update authorize view

* update js

* assets rebuild
2024-09-03 07:03:18 +10:00
David Bomba
fa369e79cf Roll back from model touchables 2024-09-02 14:07:30 +10:00
David Bomba
f83af0bf30 Fixes for tests 2024-09-02 13:47:24 +10:00
David Bomba
18fbcf75f7 Fixes for template 2024-09-02 13:34:29 +10:00
David Bomba
9cc7723949 Touch parent model after mutating docs 2024-09-02 13:19:01 +10:00
David Bomba
11d32d2569 Fixes for namespace 2024-09-02 13:10:06 +10:00
David Bomba
f117e79d43 Patches for inbound emails 2024-09-02 13:07:01 +10:00
Benjamin Beganović
9c4462d534
New payment flow: Masking with blank space (#94)
* bump simple card to .4

* update authorize

* update forte

* assets build
2024-09-02 12:57:55 +10:00
David Bomba
0fc7a27cf4
Merge pull request #9969 from turbo124/v5-develop
v5.10.27
2024-09-02 10:36:27 +10:00
David Bomba
e7479d6a41 Updates for template service properties 2024-09-02 10:35:20 +10:00
David Bomba
e5e7a17d82 Fixes for confirming gateway feesg 2024-09-02 09:00:13 +10:00
hillelcoren
06bb71f2ae Admin Portal - Selfhosted 2024-09-01 11:06:51 +00:00
hillelcoren
d4663fc469 Admin Portal - Profile 2024-09-01 11:00:36 +00:00
hillelcoren
c67d2693b5 Admin Portal - Hosted 2024-09-01 10:54:31 +00:00
David Bomba
d153ecbe1f Set blank string for signature date 2024-09-01 10:39:58 +10:00
David Bomba
a809828dc1 Minor fixes 2024-09-01 10:38:02 +10:00
David Bomba
ac3073fb4c v5.10.27 2024-08-31 08:55:46 +10:00
David Bomba
565a4d377d Remove paypal express, omnipay 2024-08-31 08:55:22 +10:00
David Bomba
b58e5f5bb7 Refactor for validation 2024-08-30 16:17:09 +10:00
David Bomba
516533c374 Move null filter to basemodel 2024-08-30 15:44:01 +10:00
David Bomba
94da1d9ded Logic to update e_invoice 2024-08-30 15:00:25 +10:00
David Bomba
c52bc3dae7 Static Analysis 2024-08-30 14:45:16 +10:00
David Bomba
f77bfe2bc7 Fixes for required fields for paytrace 2024-08-30 14:16:35 +10:00
David Bomba
f69cfb0ffa Enforce client currency_id 2024-08-30 14:08:09 +10:00
David Bomba
8eb26085f0 Updates for email template variables 2024-08-30 13:50:03 +10:00
David Bomba
1241d8226d change from sleep to usleep for mollie 2024-08-30 13:36:21 +10:00
David Bomba
a4a2e237db
Merge pull request #9960 from turbo124/v5-develop
Add reversal for failed BTC payments
2024-08-30 11:12:36 +10:00
David Bomba
cb0da8d349 updated resources 2024-08-30 11:12:09 +10:00
David Bomba
adf93942b2 Fixes for BTC Pay 2024-08-30 11:10:18 +10:00
David Bomba
93c382eae1 Minor refactors for inbound email processing 2024-08-30 10:57:43 +10:00
David Bomba
638c823722 Clean up for Peppol 2024-08-30 09:49:43 +10:00
David Bomba
c1f45a8319 Updated lock file 2024-08-30 09:19:26 +10:00
Benjamin Beganović
37892cbe7f
Paytrace: Add loaders (#93)
* nullable access payment hash data

* add loaders to js

* add loaders to authorize

* assets build
2024-08-30 09:17:40 +10:00
Benjamin Beganović
84202e77a1
Forte: Refactor authorization (#90)
* include sc in pay

* refactor authorize

* include sc in pay livewire
2024-08-30 09:17:31 +10:00
Benjamin Beganović
f01c92fbcf
New payment flow. Fixes for meta ref (#92)
* authorize

* eway

* bacs

* becs

* credit card

* przelewy24
2024-08-30 09:17:20 +10:00
Benjamin Beganović
ac19d07c24
Eway: Add loaders (#91)
* eway: add loaders

* assets build
2024-08-30 09:17:09 +10:00
David Bomba
465bf3f9d0 updates for texts 2024-08-29 18:40:01 +10:00
David Bomba
8f88c408f7 minor fixeS 2024-08-29 17:17:52 +10:00
David Bomba
4ea7c7ef63 Split parameters 2024-08-29 17:12:12 +10:00
David Bomba
918258948b Hosted changes 2024-08-29 16:57:16 +10:00
David Bomba
52630f06e3 Sending einvoices 2024-08-29 15:51:48 +10:00
David Bomba
73ed01a9bc Static Analysis 2024-08-29 15:25:20 +10:00
David Bomba
8c2b97dce5 EInvoice sending activity 2024-08-29 15:16:01 +10:00
David Bomba
6eaf3632d9 Add payment failure emails 2024-08-29 14:36:38 +10:00
David Bomba
e2365ee0f9 Stubs for sending edocs 2024-08-29 11:19:09 +10:00
David Bomba
9f7ff7dc59 Stubs for sending edocs 2024-08-29 11:17:38 +10:00
David Bomba
ac5718b6e8 Additional filters for expenses 2024-08-29 09:55:27 +10:00
David Bomba
caf22d19c0 Minor fixes 2024-08-29 08:49:53 +10:00
David Bomba
27a8d205ca Merge branch 'v5-develop' of https://github.com/turbo124/invoiceninja into v5-develop 2024-08-29 08:49:44 +10:00
David Bomba
4fa57dfc59 Fixes for import hints 2024-08-29 08:32:28 +10:00
hillelcoren
7e5a1d1893 Admin Portal - Selfhosted 2024-08-28 19:56:09 +00:00
hillelcoren
14685a50a2 Admin Portal - Profile 2024-08-28 19:45:12 +00:00
hillelcoren
caade65be3 Admin Portal - Hosted 2024-08-28 19:39:01 +00:00
paulwer
0b4eaf9d4f fixes 2024-08-28 10:20:43 +02:00
paulwer
7ff7ce6f19 brevo fixes 2024-08-28 10:08:48 +02:00
paulwer
984af8750a fixes 2024-08-28 09:56:01 +02:00
paulwer
5ecb2033db fixes 2024-08-28 09:53:38 +02:00
David Bomba
6c0c895ccd Updates for BGN 2024-08-28 17:31:19 +10:00
paulwer
2a28d8c976 fixes 2024-08-28 09:29:50 +02:00
paulwer
5da3ae7770 fixes 2024-08-28 09:29:11 +02:00
David Bomba
29068cb01e Minor fixes 2024-08-28 17:20:41 +10:00
David Bomba
ee8a4b6ab6 Fixes for tests 2024-08-28 17:07:17 +10:00
paulwer
144d52b444 fixes 2024-08-28 08:44:08 +02:00
paulwer
2c7bf4f44d fixes 2024-08-28 08:18:39 +02:00
paulwer
b9f56f0e30 fixes postmark 2024-08-28 08:07:37 +02:00
paulwer
1f92ea0108 fixes for validating expense_mailbox in company request 2024-08-28 07:33:03 +02:00
paulwer
13dae4f524 Merge branch 'v5-develop' of https://github.com/invoiceninja/invoiceninja into feature-inbound-email-expenses 2024-08-28 07:02:43 +02:00
David Bomba
fa38433de9 Updates for null properties 2024-08-28 14:05:39 +10:00
David Bomba
b4c9caa4c7 Minor fixes 2024-08-28 12:48:08 +10:00
David Bomba
17602f5fcd self host einvoicing 2024-08-28 12:13:07 +10:00
David Bomba
3ad93ac8aa Add back missing includE 2024-08-28 11:50:52 +10:00
David Bomba
5bc756bc83 Fixes for test 2024-08-28 11:18:13 +10:00
Benjamin Beganović
48fdf6a85c
New payment flow: Various fixes (#89)
* assets builds

* authorize: use simple-card from asset

* forte: use simple-card from asset

* remove @invoiceninja/simple-card from package

* update usages

* stripe: ach fix

* stripe: alipay fix

* stripe: bacs fix

* stripe: acss fix

* stripe: giropay fix

* assets build
2024-08-28 11:17:03 +10:00
David Bomba
bc1510582e Add legal entity 2024-08-28 11:12:47 +10:00
David Bomba
5f43c5e2a2 Fixes for tests 2024-08-28 11:02:57 +10:00
David Bomba
0905bd2f58 Storecove router 2024-08-28 10:48:08 +10:00
David Bomba
b94d54f3dd Static Analysis 2024-08-28 08:47:28 +10:00
David Bomba
148f4c2c6d Fixes for template mocked data 2024-08-28 08:45:22 +10:00
David Bomba
a58967dcab Fixes for migration file 2024-08-27 22:39:36 +10:00
David Bomba
3df5e6ca5c self host e-invoicing 2024-08-27 20:22:51 +10:00
David Bomba
02cbcbd5ed Add legal entity id to model 2024-08-27 14:47:18 +10:00
David Bomba
620bdc61dd Static Analysis 2024-08-27 11:49:01 +10:00
David Bomba
3e39a58c8e Fixes for tests 2024-08-27 11:36:31 +10:00
David Bomba
376b728e68 Tests forbank processing rules 2024-08-27 10:38:16 +10:00
David Bomba
47311c5f2c Tests for rules 2024-08-27 10:06:11 +10:00
David Bomba
999ccfd990 latest assets 2024-08-27 09:43:07 +10:00
David Bomba
df914450e2
Merge pull request #9948 from turbo124/v5-develop
Minor fixes.
2024-08-27 09:42:24 +10:00
David Bomba
0fa4aa6a1f
Merge pull request #9945 from beganovich/1422-rotessa-final2
Rotessa: New payment flow
2024-08-27 09:33:38 +10:00
Benjamin Beganović
fba29de459
New payment flow: Various fixes (#88)
* checkout: fixes for view

* alipay: fixes for method implementation

* checkout: fixes for instant payments

* livewire: revert back the local patch

* remove livewire local patch
2024-08-27 07:42:39 +10:00
Benjamin Beganović
73bc91f743 rotessa acss 2024-08-26 18:21:21 +02:00
David Bomba
d074dd7edb Refactor for QB 2024-08-26 20:17:51 +10:00
David Bomba
5f32baceef Webhook support for QB 2024-08-26 18:39:23 +10:00
David Bomba
4e5ebc235d Add hash to products 2024-08-26 16:54:22 +10:00
David Bomba
7bd02ab097 Add hash to products 2024-08-26 16:25:46 +10:00
David Bomba
98326f1315 minor adjustments 2024-08-26 16:20:48 +10:00
David Bomba
406cb5a334 Fixes for tests 2024-08-26 16:14:54 +10:00
David Bomba
7f226fe5d2 minor adjustments 2024-08-26 15:48:48 +10:00
David Bomba
8f82b27e50 Refactor QB 2024-08-26 09:49:22 +10:00
Benjamin Beganović
19556eb970
Fixes for CVV issues on Authorize & Forte (#84)
* fixes for forte

* fixes for authorize
2024-08-26 08:52:50 +10:00
David Bomba
b43c9ee59b Quickbooks settings 2024-08-26 08:24:51 +10:00
David Bomba
7745d6db17 new .js 2024-08-25 07:39:32 +10:00
David Bomba
656a115eba Improve rate limiting 2024-08-25 07:39:14 +10:00
David Bomba
3569cef5dd remove backticks 2024-08-24 08:26:59 +10:00
Benjamin Beganović
3d69a0b88c
Apply Livewire patch to load assets async (#85)
* apply livewire local patch

* assets build

* remove manual chunking

* assets build
2024-08-24 08:18:21 +10:00
David Bomba
18864e06be
Merge pull request #9942 from turbo124/v5-develop
Sort filters for expense.payment_dates
2024-08-24 07:32:53 +10:00
David Bomba
8076eb6d06 Improve filters for expenses 2024-08-24 07:32:03 +10:00
David Bomba
b1f73f97de Qb 2024-08-23 22:55:31 +10:00
David Bomba
6145dbdb4d
Merge pull request #9921 from kaiwalyakoparkar/add-elestio
feat: Added Elestio as one-click deploy option
2024-08-23 22:09:34 +10:00
David Bomba
4eee3286f2
Merge branch 'v5-develop' into add-elestio
Signed-off-by: David Bomba <turbo124@gmail.com>
2024-08-23 22:09:26 +10:00
hillelcoren
4e8de2d8ce Admin Portal - Selfhosted 2024-08-23 09:52:26 +00:00
hillelcoren
1e812d686a Admin Portal - Profile 2024-08-23 09:46:15 +00:00
hillelcoren
0dad4d2743 Admin Portal - Hosted 2024-08-23 09:39:57 +00:00
David Bomba
b24d843164 Updates for QB 2024-08-23 14:17:37 +10:00
David Bomba
ac742cc893 Updated translations 2024-08-23 09:29:36 +10:00
David Bomba
f8d9dd52d3 translations 2024-08-23 09:29:10 +10:00
David Bomba
2eff70c85a
Merge pull request #9937 from turbo124/v5-develop
v5.10.26
2024-08-23 08:10:57 +10:00
David Bomba
6f374b3c43 Update version 2024-08-23 08:08:28 +10:00
David Bomba
13b24cc03e
Merge pull request #9935 from turbo124/v5-develop
v5.10.25
2024-08-22 17:19:43 +10:00
David Bomba
829451641b v5.10.25 2024-08-22 17:17:05 +10:00
David Bomba
8160af4ef4 PHP CS Fixer 2024-08-22 16:57:52 +10:00
David Bomba
74411da11f Fixes for tests 2024-08-22 16:57:13 +10:00
David Bomba
c9eb5750b4 Rollback for new payment flow 2024-08-22 16:45:37 +10:00
David Bomba
036aca49a4 Rollback for new payment flow 2024-08-22 16:45:06 +10:00
David Bomba
af92ce8d37 Merge new payment flows 2024-08-22 08:31:18 +10:00
David Bomba
e59a652263 minor fies 2024-08-22 08:20:08 +10:00
David Bomba
3f5f2d66cc Minor fixes 2024-08-22 08:18:19 +10:00
David Bomba
6607b23046
Merge pull request #9934 from turbo124/v5-develop
Fixes for inter EU tax rules
2024-08-22 08:15:40 +10:00
David Bomba
f258bdb78e Typo 2024-08-22 08:14:54 +10:00
David Bomba
d36515367b Fixes for pp cc 2024-08-22 08:14:28 +10:00
David Bomba
fd6d60327b Rules for DE 2024-08-22 07:45:07 +10:00
Benjamin Beganović
044b4bce72
Fixes for Forte & Authorize.net (#83)
* configure manual chunks for forte & authorize

* assets build
2024-08-22 07:44:57 +10:00
David Bomba
764545a39d
Merge pull request #9931 from CodeShakingSheep/add-yunohost
feat: Add YunoHost to self-hosted options
2024-08-22 07:17:35 +10:00
CodeShakingSheep
4bf1527abe
Update README.md
Add YunoHost to self-hosted options

Signed-off-by: CodeShakingSheep <19874562+CodeShakingSheep@users.noreply.github.com>
2024-08-21 11:18:34 -05:00
hillelcoren
28e493d167 Admin Portal - Selfhosted 2024-08-21 16:07:55 +00:00
hillelcoren
7aeb7c6bc7 Admin Portal - Profile 2024-08-21 16:01:34 +00:00
hillelcoren
4fed2d201f Admin Portal - Hosted 2024-08-21 15:55:09 +00:00
hillelcoren
bf31abce09 Admin Portal - Selfhosted 2024-08-21 12:21:01 +00:00
hillelcoren
387582b019 Admin Portal - Profile 2024-08-21 12:14:42 +00:00
hillelcoren
e5795563f3 Admin Portal - Hosted 2024-08-21 12:08:29 +00:00
David Bomba
e63c50f58f Refactors for Bank Transactions 2024-08-21 17:46:07 +10:00
David Bomba
dfca75229d Additional rules for credits 2024-08-21 17:19:44 +10:00
David Bomba
c894cdff8b Refactor for quickbooks 2024-08-21 16:49:48 +10:00
David Bomba
c231c9186f Refactor for quickbooks 2024-08-21 15:07:52 +10:00
David Bomba
f8e06d7ca3 Refactor QB 2024-08-21 13:22:46 +10:00
David Bomba
9af3ffb77c Refactor 2024-08-21 13:18:21 +10:00
David Bomba
9c225458c6 Fixes for QB pr 2024-08-21 13:04:09 +10:00
David Bomba
ed84689ca0
Merge pull request #9924 from turbo124/v5-develop
Translations
2024-08-21 12:00:32 +10:00
David Bomba
37822d7a0d
Merge pull request #9917 from M-E-Development-Design/feature/import-quickbooks
Feature/import quickbooks
2024-08-21 12:00:02 +10:00
David Bomba
18bd957167 Update for license model 2024-08-21 10:48:13 +10:00
David Bomba
662989169f Quotas for einvoice 2024-08-21 10:20:32 +10:00
David Bomba
28de616bbf Translations 2024-08-21 09:54:15 +10:00
David Bomba
827eb8de19
Merge pull request #9923 from turbo124/v5-develop
Purchase Order Accept Webhook
2024-08-21 09:36:52 +10:00
David Bomba
87639f3c73 Add accept purchase order webhook 2024-08-21 09:35:54 +10:00
David Bomba
c904a49aaf Additional granularity for mailer 2024-08-21 07:41:46 +10:00
Kaiwalya Koparkar
f34a1eb755 feat: Added Elestio as one-click deploy option 2024-08-20 15:48:02 +00:00
David Bomba
e8eaba44ed Translations 2024-08-20 14:20:24 +10:00
David Bomba
42c727e995
Merge pull request #9918 from turbo124/v5-develop
Fix for calculate taxes with Recurring Invoices
2024-08-20 11:53:49 +10:00
David Bomba
0615ba25ed Fixes for calculate taxes - edge case with Recurring Invoice 2024-08-20 11:53:10 +10:00
David Bomba
609d464ac7 minor fixes 2024-08-19 19:17:58 +10:00
David Bomba
aed30cb572 Peppol 2024-08-19 14:06:27 +10:00
David Bomba
4e8197a623 peppol 2024-08-19 11:45:34 +10:00
David Bomba
af73fc2e51 Improve expense XML parsing 2024-08-19 07:42:49 +10:00
David Bomba
05c063e4d3
Merge pull request #9912 from beganovich/gh-1966
Update translations
2024-08-19 06:48:19 +10:00
David Bomba
0500f39fa6
Merge pull request #9914 from LarsK1/v5-develop
Fixes for ZUGFeRD
2024-08-19 06:46:43 +10:00
karneaud
979b8ddcb2 remove logger 2024-08-17 11:51:01 -04:00
karneaud
72938bf5ad update tranformation keys 2024-08-17 11:25:17 -04:00
karneaud
73e596d29c group common methods into trait 2024-08-17 11:24:53 -04:00
karneaud
43b95125f0 add logic for import payment entity 2024-08-17 11:24:08 -04:00
Lars Kusch
1ab0cbcc63
Merge branch 'v5-develop' into v5-develop
Signed-off-by: Lars Kusch <lars@lars-kusch.de>
2024-08-17 15:16:23 +02:00
Lars Kusch
756ea9521c
Update ZugferdEDokument.php 2024-08-17 15:15:31 +02:00
Benjamin Beganović
0e2edde2a5
fix logic with under over payments (#82) 2024-08-17 07:54:18 +10:00
hillelcoren
b251132f09 Admin Portal - Selfhosted 2024-08-16 12:16:14 +00:00
hillelcoren
c02bedfd97 Admin Portal - Profile 2024-08-16 12:10:04 +00:00
hillelcoren
d9f8cba6d8 Admin Portal - Hosted 2024-08-16 12:03:50 +00:00
hillelcoren
66df34b586 Admin Portal - Profile 2024-08-16 09:59:05 +00:00
hillelcoren
8d546ce1f5 Admin Portal - Hosted 2024-08-16 09:53:03 +00:00
karneaud
3e0c6f2986 updae quickbooks sdk 2024-08-15 21:39:57 -04:00
Kendall Arneaud
d85f0b98fd
Merge pull request #30 from M-E-Development-Design/v5-develop
V5 develop
2024-08-15 21:14:31 -04:00
karneaud
ee77bb11fc merge conflict from source 2024-08-15 21:13:07 -04:00
karneaud
fda7c693a3 modify method 2024-08-15 20:54:18 -04:00
karneaud
2e3b89288d add invoice transformer method 2024-08-15 20:54:00 -04:00
karneaud
7e8d82384a add invoice respository 2024-08-15 20:53:28 -04:00
karneaud
193e35e21b type cast values. check has client 2024-08-15 20:53:11 -04:00
karneaud
b4f8c0a7ba clean line items. test for invoice 2024-08-15 20:52:22 -04:00
Benjamin Beganović
05d7211c4c
PayPal: New payment flow (#81)
* extract payment view and data

* scaffold pay livewire

* express

* fix for checkout interface

* card

* rest

* ppcp

* assets build

* fix for duplicate pay button
2024-08-16 07:27:17 +10:00
David Bomba
57866333a8 Minor fixes 2024-08-16 07:26:03 +10:00
Benjamin Beganović
073cf60030 update translations 2024-08-15 11:23:58 +02:00
David Bomba
9bdb3d77b7
Merge pull request #9911 from turbo124/v5-develop
v5.10.24
2024-08-15 10:39:09 +10:00
David Bomba
824787b2f2 v5.10.24 2024-08-15 08:51:52 +10:00
David Bomba
40ecb6a248 Fixes for subs v1 + setting guard on repo activities 2024-08-15 07:32:58 +10:00
David Bomba
2481a44c6d
Merge pull request #9908 from turbo124/v5-develop
v5.10.23
2024-08-14 23:35:22 +10:00
David Bomba
f938f371e5 v5.10.23 2024-08-14 23:34:42 +10:00
David Bomba
766a1955ee Ensure no recalculations once locked 2024-08-14 23:34:17 +10:00
David Bomba
ba0765ac6f
Merge pull request #9905 from turbo124/v5-develop
v5.10.22
2024-08-14 20:20:24 +10:00
David Bomba
d0acea818a v5.10.22 2024-08-14 20:19:51 +10:00
David Bomba
e1dc5d1176 Improvements for forte 2024-08-14 20:19:37 +10:00
David Bomba
8c62026db3 Fixes for forte token billing 2024-08-14 13:32:26 +10:00
David Bomba
645aca9f63 Adjustments for types 2024-08-14 08:34:57 +10:00
karneaud
4d51bbc9a2 fix namespace 2024-08-13 12:36:12 -04:00
karneaud
9dcf0fac77 add product/items logic 2024-08-13 12:35:50 -04:00
karneaud
7f9010b9a5 fix namespace 2024-08-13 12:35:04 -04:00
karneaud
b057908164 use repo and sdk for routines instead of service 2024-08-13 12:34:45 -04:00
David Bomba
47c5498fbe
Merge pull request #9899 from turbo124/v5-develop
v5.10.21
2024-08-13 15:30:46 +10:00
David Bomba
8f3de46811 v5.10.21 2024-08-13 15:15:39 +10:00
David Bomba
0777c6e43c Extend webhook delay for mollie 2024-08-13 15:14:41 +10:00
David Bomba
f59006aedd Improve gateway fee toggles 2024-08-13 14:30:44 +10:00
David Bomba
2ffe9bb83a Rate limit actions regardless of ids 2024-08-13 13:14:09 +10:00
David Bomba
a58398c093
Merge pull request #9898 from turbo124/v5-develop
Add search on product_key and notes via query filters
2024-08-13 09:36:15 +10:00
David Bomba
2449757021 Update entity filters 2024-08-13 09:35:31 +10:00
David Bomba
9554de63b2 Harvest client routing codes 2024-08-12 20:51:01 +10:00
David Bomba
913a3e3ad9 Add identifiers for storecove 2024-08-12 17:37:26 +10:00
David Bomba
a8c7d49528 entity history query 2024-08-12 14:30:19 +10:00
David Bomba
be00f173c4 Updated mail queries 2024-08-12 14:14:31 +10:00
David Bomba
5fbf1eea1e
Merge pull request #9891 from turbo124/v5-develop
Add log time to task exports
2024-08-12 08:37:52 +10:00
David Bomba
92f1ef98d0 Add in task item log entry to task exports 2024-08-12 08:37:23 +10:00
David Bomba
344603123a Small fixes for payment email logic 2024-08-11 09:27:13 +10:00
David Bomba
489476feeb Fixes for quotas 2024-08-10 08:25:32 +10:00
Kendall Arneaud
ae75f7228c
Merge pull request #27 from M-E-Development-Design/v5-develop
V5 develop
2024-08-09 17:55:48 -04:00
Kendall Arneaud
8b5db9827a
Merge branch 'feature/import-quickbooks' into v5-develop
Signed-off-by: Kendall Arneaud <kendall.arneaud@gmail.com>
2024-08-09 17:55:38 -04:00
Kendall Arneaud
ea45200526
Merge pull request #26 from M-E-Development-Design/addon/alter-companies
Addon/alter companies
2024-08-09 17:53:55 -04:00
David Bomba
ec144b4181 Fixes for Rotessa 2024-08-09 15:39:16 +10:00
David Bomba
2baebffc32 Updates for multi invoice payment flow 2024-08-09 14:44:39 +10:00
David Bomba
c4f93e4d12 Updates for payment flow 2024-08-09 13:04:59 +10:00
David Bomba
fb57d4d9de Improve new flow 2024-08-09 12:48:21 +10:00
Benjamin Beganović
6f4428f6ab
Forte: New payment flow (#71)
* pass livewirePaymentView & processPaymentView thru base driver

* forte: ach

* add paymentData to the interface

* forte cc

* simple card

* forte cc

* clean up

---------

Co-authored-by: David Bomba <turbo124@gmail.com>
2024-08-09 09:11:31 +10:00
Benjamin Beganović
852efd3989
New payment flow: Refactor base driver (#70)
* pass livewirePaymentView & processPaymentView thru base driver

* add paymentData to the interface
2024-08-09 09:09:42 +10:00
Benjamin Beganović
4e608eb242
GoCardless: New payment flow (#72)
* pass livewirePaymentView & processPaymentView thru base driver

* gocardless
2024-08-09 09:09:29 +10:00
Benjamin Beganović
6aefbbf2c6
Mollie: New payment flow (#73)
* pass livewirePaymentView & processPaymentView thru base driver

* add paymentData to the interface

* mollie

* credit card
2024-08-09 09:09:20 +10:00
Benjamin Beganović
f966a2b846
BTCPay: New payment flow (#76)
* pass livewirePaymentView & processPaymentView thru base driver

* add paymentData to the interface

* btcpay
2024-08-09 09:09:04 +10:00
Benjamin Beganović
59666dc5db
Braintree: New payment flow (#77)
* pass livewirePaymentView & processPaymentView thru base driver

* add paymentData to the interface

* braintree
2024-08-09 09:08:54 +10:00
Benjamin Beganović
6351e209d2
Paytrace: New payment flow (#74)
* pass livewirePaymentView & processPaymentView thru base driver

* add paymentData to the interface

* paytrace
2024-08-09 09:08:36 +10:00
Benjamin Beganović
398e9d3a98
Payfast: New payment flow (#78)
* pass livewirePaymentView & processPaymentView thru base driver

* add paymentData to the interface

* payfast
2024-08-09 09:08:03 +10:00
Benjamin Beganović
dd3e98eb30
Razorpay: New payment flow (#79)
* pass livewirePaymentView & processPaymentView thru base driver

* add paymentData to the interface

* razorpay
2024-08-09 09:08:00 +10:00
Benjamin Beganović
0b01bacb78
update instant payment refs (#80) 2024-08-09 09:07:55 +10:00
Benjamin Beganović
dc401a4da6
Square: New payment flow (#75)
* pass livewirePaymentView & processPaymentView thru base driver

* square
2024-08-09 09:07:51 +10:00
Benjamin Beganović
b63e413d6e
eway (#69) 2024-08-09 09:07:35 +10:00
Benjamin Beganović
0fff78b0a0
Authorize.net: New payment flow (#68)
* fixes for validation errors

* authorize.net

* pass livewirePaymentView & processPaymentView thru base driver

* add paymentData to the interface

* authorize.net credit card
2024-08-09 09:07:23 +10:00
karneaud
f2755aa1f4 update tests 2024-08-08 12:56:36 -04:00
karneaud
6cea02684c add quicbooks columns for companies 2024-08-08 12:56:15 -04:00
karneaud
fe2248d097 repository for token storage logic 2024-08-08 12:56:00 -04:00
karneaud
6d0952231a get the tokens from store or sdk 2024-08-08 12:55:17 -04:00
karneaud
2fc4b3d419 fix class not found error 2024-08-08 12:54:41 -04:00
karneaud
ba40fc54ba adjust for multiple entities 2024-08-08 12:54:23 -04:00
karneaud
d79dce6669 propertly run import for multiple entities. fix caching logic 2024-08-08 12:53:45 -04:00
karneaud
c7817f9bfd get and refresh tokens 2024-08-08 12:50:29 -04:00
David Bomba
286b2087cd Updated URL for trouble shooting 2024-08-08 17:48:24 +10:00
David Bomba
a8e313b5e9 Working on Peppol 2024-08-08 14:16:35 +10:00
David Bomba
5bd411b394 Working on Peppol 2024-08-08 12:32:31 +10:00
David Bomba
c44a3a971b
Merge pull request #9883 from turbo124/v5-develop
Add payment balance as an accessible variable
2024-08-08 09:58:38 +10:00
David Bomba
5bbee220a2 Add payment balance as an accessible variable 2024-08-08 09:58:19 +10:00
David Bomba
3d9cbf5b91
Merge pull request #9882 from turbo124/v5-develop
v5.10.20
2024-08-08 09:48:33 +10:00
David Bomba
7abd210623 V5.10.20 2024-08-08 09:48:09 +10:00
David Bomba
0234da3d63 Fixes for auto taxes with exempt taxes in EU 2024-08-08 09:47:50 +10:00
David Bomba
f0d802839e Minor fixeS 2024-08-08 09:32:41 +10:00
David Bomba
20899e2bea Minor fixeS 2024-08-08 09:32:23 +10:00
David Bomba
00ad4bf864 Fixes for grouping payment links 2024-08-08 07:01:24 +10:00
Kendall Arneaud
775a60b71d
Merge branch 'invoiceninja:v5-develop' into v5-develop 2024-08-07 13:37:56 -04:00
David Bomba
ac701863dc Working on Peppol 2024-08-07 12:12:16 +10:00
David Bomba
00d6c13344 Fixes for paypal 2024-08-07 11:09:56 +10:00
David Bomba
2214b546ed Fixes for tests 2024-08-07 10:15:21 +10:00
David Bomba
50a9a917b3 Working on Peppol 2024-08-07 09:50:19 +10:00
David Bomba
6fa753a149 Expense category filters 2024-08-07 08:09:18 +10:00
David Bomba
29867c3c77
Merge pull request #9875 from turbo124/v5-develop
Minor fixes
2024-08-06 19:22:56 +10:00
David Bomba
19cfee10a0 Minor fixes 2024-08-06 19:21:42 +10:00
David Bomba
2027cb1bc0
Merge pull request #9874 from turbo124/v5-develop
Fixes for subscriptions
2024-08-06 19:01:48 +10:00
David Bomba
2f03a13d34 Fixes for paypal in subscriptions 2024-08-06 18:57:19 +10:00
David Bomba
36fef6beb3 Improvements for twig 2024-08-06 18:21:03 +10:00
David Bomba
7c6732e896 Minor adjustments for webhooks 2024-08-06 14:04:03 +10:00
David Bomba
7acb369408 Calculations for cards on dashbaord 2024-08-06 08:22:00 +10:00
David Bomba
2a4dd7e593 Updates for chart queries 2024-08-05 18:52:34 +10:00
David Bomba
a8362bf5b0 Updated translations 2024-08-05 15:08:33 +10:00
David Bomba
02c85e9330 Improved error handling with paypal 2024-08-05 15:04:22 +10:00
David Bomba
08f9443c82 Static analysis 2024-08-05 14:04:05 +10:00
David Bomba
b81eb57744 Updates / copyright 2024-08-05 14:02:58 +10:00
David Bomba
20573b362c Remove paypal express, omnipay 2024-08-05 11:57:42 +10:00
David Bomba
90eccfcaa0 Updated company migration 2024-08-05 08:56:31 +10:00
David Bomba
a2dc354e2c
Merge pull request #9865 from turbo124/v5-develop
Fixes for recurring invoice queries
2024-08-05 08:40:06 +10:00
David Bomba
dea57e0780 Fixes for recurring invoice queries 2024-08-05 08:37:21 +10:00
David Bomba
d69d465abf Fixes for recurring invoice queries 2024-08-04 20:21:30 +10:00
David Bomba
7e986b82c7 Add includes 2024-08-04 18:46:37 +10:00
David Bomba
689fe9218d Roll back routeserviceprovider changes 2024-08-04 18:28:27 +10:00
David Bomba
0edb03943b Updates for PRedis 2024-08-04 18:22:00 +10:00
David Bomba
7d34eab0f0
Merge pull request #9860 from turbo124/v5-develop
Updated CSS
2024-08-04 17:30:30 +10:00
David Bomba
2214455364 Updated CSS 2024-08-04 17:26:48 +10:00
David Bomba
52ba09044d
Merge pull request #9859 from turbo124/v5-develop
Updated CSS
2024-08-04 17:11:30 +10:00
David Bomba
5e9ad43281 Updated CSS 2024-08-04 17:11:10 +10:00
David Bomba
e309933d2e
Merge pull request #9858 from turbo124/v5-develop
Remove migration for tax models
2024-08-04 17:05:22 +10:00
David Bomba
2373f6e508 Remove migration for tax models 2024-08-04 17:05:03 +10:00
David Bomba
ed0cb15013
Merge pull request #9857 from turbo124/v5-develop
Fixes for translations in client portal
2024-08-04 16:55:45 +10:00
David Bomba
d7dfd4ab65 Fixes for translations in client portal 2024-08-04 16:55:18 +10:00
David Bomba
620bd18cf9 Improve data errors for twig 2024-08-04 07:28:20 +10:00
karneaud
32c0006825 move get methods for access token 2024-08-02 21:48:15 -04:00
karneaud
bacd5a0f0d fix routes. use factory 2024-08-02 21:47:12 -04:00
karneaud
eaa12e8b31 add quickbooks sdk factory 2024-08-02 21:43:52 -04:00
karneaud
5a28a81f0f update lock 2024-08-02 21:43:35 -04:00
Kendall Arneaud
08f33ac3e7
Merge pull request #20 from M-E-Development-Design/v5-develop
V5 develop
2024-08-02 10:02:59 -04:00
Kendall Arneaud
7c1f892ec2
Merge branch 'feature/import-quickbooks' into v5-develop
Signed-off-by: Kendall Arneaud <kendall.arneaud@gmail.com>
2024-08-02 10:02:45 -04:00
karneaud
32aad06308 update quickbooks controller tests 2024-08-01 22:34:36 -04:00
karneaud
ab5e05485e add get state 2024-08-01 22:34:13 -04:00
karneaud
b3ab9e468c separate auth logic from entity logic 2024-08-01 22:33:44 -04:00
karneaud
af47d5d8e4 move quickbooks routes to provider 2024-08-01 22:33:13 -04:00
karneaud
6f2d139f45 bind instead of singleton 2024-08-01 22:32:45 -04:00
karneaud
014a3c1f5c added middleware with validation. refactored methods 2024-08-01 22:32:20 -04:00
paulwer
7b60c2c5b9 Merge branches 'feature-inbound-email-expenses' and 'feature-inbound-email-expenses' of https://github.com/paulwer/invoiceninja; branch 'v5-develop' of https://github.com/invoiceninja/invoiceninja into feature-inbound-email-expenses 2024-08-01 09:56:46 +02:00
paulwer
ce77eff7cb Merge branch 'v5-develop' of https://github.com/invoiceninja/invoiceninja into feature-inbound-email-expenses 2024-07-31 07:59:26 +02:00
karneaud
404933625f import controller test for quickbooks 2024-07-30 14:19:46 -04:00
karneaud
6d40891c74 start at 0 2024-07-30 14:19:27 -04:00
karneaud
90b6907e71 modify to use quickbooks service and store data in cache 2024-07-30 14:19:15 -04:00
karneaud
3ba4533b28 add service tests for quickbooks 2024-07-29 16:18:40 -04:00
karneaud
d5e499febd add api service for quickboks 2024-07-29 16:18:17 -04:00
karneaud
79ed325a29 add sdk wrapper 2024-07-29 16:17:29 -04:00
karneaud
85220bf58f add transformer for underline raw data 2024-07-29 16:17:09 -04:00
karneaud
4c3829b8c1 add repository for quickbooks data 2024-07-29 16:16:48 -04:00
karneaud
ee334fd974 add quickbooks service provider 2024-07-29 16:16:10 -04:00
karneaud
6e587f96cf add intuit sdk depdency 2024-07-29 16:15:43 -04:00
Kendall Arneaud
241e70863f
Merge pull request #10 from karneaud/v5-develop
V5 develop
2024-07-22 20:11:59 -04:00
karneaud
1d1a01fcd1 add quickbooks imports controller test 2024-07-22 20:04:02 -04:00
karneaud
7200591b1e update mock refs 2024-07-22 20:03:46 -04:00
karneaud
245fc2ad77 restructure mocks 2024-07-22 20:03:27 -04:00
karneaud
630c48193d add quicbooks controller/routes 2024-07-22 20:02:13 -04:00
karneaud
8e5c6509c2 add test quickbooks ingest job 2024-07-19 13:05:19 -04:00
karneaud
207c3ec80a add inget job for quickbooks 2024-07-19 13:04:54 -04:00
karneaud
b43aa77ff8 fixed class not found 2024-07-19 13:04:40 -04:00
karneaud
473f9ea0a0 update test case for import invoice feature 2024-07-17 12:34:26 -04:00
karneaud
7520b6318d refactor to include client object/ id 2024-07-17 12:34:09 -04:00
karneaud
b1d2f85af3 add import invoices feature 2024-07-17 12:33:51 -04:00
karneaud
596ed1a662 update test. test for client 2024-07-16 13:03:37 -04:00
karneaud
519bb57368 update sample data 2024-07-16 13:03:17 -04:00
karneaud
e3135a8e99 added get client info 2024-07-16 13:02:59 -04:00
Benjamin Beganović
0de492d96f
Stripe: New payment flow (#67)
* stripe: ach

* stripe: klarna

* stripe: bank transfer

* assets build

* stripe: bacs

* stripe: bancontact

* stripe: becs

* stripe: eps

* stripe: fpx

* stripe: giropay

* stripe: ideal

* stripe: przelewy24

* stripe: sepa

* stripe: sofort

* assets build

* assets build

* pass context payload into livewirePaymentView

* update checkout.com

* update livewire method interface

* stripe: acss

* align methods with interface (array $data)
2024-07-16 18:43:55 +10:00
karneaud
1a4cd7d3f6 add test case for product transformer 2024-07-15 21:30:09 -04:00
karneaud
2df99a312e update quickbook test for product import 2024-07-15 21:29:51 -04:00
karneaud
4cde94f203 add item sample data 2024-07-15 21:29:32 -04:00
karneaud
a1d3247d52 add product transformer 2024-07-15 21:29:17 -04:00
karneaud
282fe44c85 fixed error missing 2nd param 2024-07-15 21:29:04 -04:00
karneaud
57a62a054b add product import method 2024-07-15 21:28:22 -04:00
karneaud
0941d1ae32 test data 2024-07-15 15:08:04 -04:00
karneaud
4d431935e1 add test case for quickbooks import class 2024-07-15 15:07:49 -04:00
karneaud
367d27258c add company id to array 2024-07-15 15:07:27 -04:00
karneaud
53b6f65add add import class for quickbooks 2024-07-15 15:06:52 -04:00
Kendall Arneaud
abfd99fe7f
Merge pull request #9 from karneaud/v5-develop
V5 develop
2024-07-12 11:09:30 -04:00
karneaud
c2ef811faa add transformer tests 2024-07-12 11:02:36 -04:00
karneaud
d11cc1d010 add test sample data 2024-07-12 11:02:22 -04:00
karneaud
4531df2759 add test data 2024-07-12 11:01:55 -04:00
karneaud
7a750f930a add client and invoice transformers 2024-07-12 11:01:27 -04:00
Benjamin Beganović
1f7904e317
Refactor context passing between methods and Livewire (#65)
* checkout.com credit card payment for livewire

* implement interface for livewire view

* livewire method interface

* implement interfaces

* assets production build

* checkout.com: credit card

* stripe: credit card

* lift up logic from process payment component

* update stripe payment view logic

* wait fn for mounting existing JS

* credit card: simplify data passing

* stripe: browser pay

* stripe cc: remove getData

* stripe: cc

* stripe: alipay

* checkout :cc

* stripe: apple pay

* stripe: browser pay

* assets production build
2024-07-10 09:55:36 +10:00
Benjamin Beganović
18cd647e43
improve loading states (#66) 2024-07-09 12:02:54 +10:00
David Bomba
e63598271b Adjustments for payment flow 2024-07-05 15:33:46 +10:00
Benjamin Beganović
2a1947ea6e
New payment flow (#64)
* remove context from invoice-pay

* withsecurecontext trait

* update usages

* wip

* wip

* wip

* wip

* wip
2024-07-05 15:13:38 +10:00
paulwer
f07fde39aa fixes 2024-07-02 20:20:28 +02:00
paulwer
36745bfabc Merge branches 'feature-inbound-email-expenses' and 'feature-inbound-email-expenses' of https://github.com/paulwer/invoiceninja; branch 'v5-develop' of https://github.com/invoiceninja/invoiceninja into feature-inbound-email-expenses 2024-07-02 20:20:04 +02:00
David Bomba
f25469a288 Required fields 2024-07-02 19:20:55 +10:00
David Bomba
ee90539bd8 improvements for validation of over/under payments 2024-07-02 18:32:14 +10:00
David Bomba
01312996d8 Working on integrating multiple invoice payments 2024-07-02 17:09:46 +10:00
David Bomba
73c1f1b767 improvements for validation of over/under payments 2024-07-02 16:13:52 +10:00
David Bomba
aa5695ac45 Improvements fo reactivity 2024-07-02 15:06:45 +10:00
David Bomba
6f5a08f87d new payment flow 2024-07-02 14:54:50 +10:00
David Bomba
e1be33314e Improve spinners between loads 2024-07-02 12:35:28 +10:00
David Bomba
4a3f8278ea Updates for new payment flow 2024-07-02 08:20:10 +10:00
David Bomba
825d18fbae Updates for new payment flow 2024-07-01 15:13:58 +10:00
David Bomba
5761f6dc34 Updates for payment flow 2024-07-01 09:39:40 +10:00
David Bomba
a83cb0c3b2 working on payment flow 2024-07-01 07:44:03 +10:00
paulwer
b85e846de5 fixes 2024-06-30 13:07:09 +02:00
paulwer
dbcf32da26 minor fixes 2024-06-30 13:06:30 +02:00
paulwer
19cdfcf094 Merge branch 'v5-develop' of https://github.com/invoiceninja/invoiceninja into feature-inbound-email-expenses 2024-06-28 20:41:55 +02:00
David Bomba
c7cc0e084f updates for html invoice layout 2024-06-28 15:41:48 +10:00
David Bomba
682147a26e Updated - now trying to get vite and livewire to play nice 2024-06-28 12:42:44 +10:00
David Bomba
54af9cc667 Add new entry point for livewire component payments 2024-06-28 11:12:56 +10:00
David Bomba
7189c494ea Updated flow 2024-06-27 10:29:36 +10:00
David Bomba
fd7c28880c Payment methods 2024-06-27 09:13:49 +10:00
paulwer
b8abf12fd4 Merge branch 'v5-develop' of https://github.com/invoiceninja/invoiceninja into feature-inbound-email-expenses 2024-06-26 19:26:08 +02:00
paulwer
ec0df164ce log error in all cases for better debugging experience + minor find vendor improvements 2024-06-26 19:24:57 +02:00
paulwer
f44559869a comments 2024-06-26 19:05:14 +02:00
paulwer
8616adb437 fixes 2024-06-26 19:00:09 +02:00
paulwer
96b60f4ee2 fix for api error and requested changes 2024-06-26 17:34:32 +02:00
paulwer
7e9e33b846 fixes 2024-06-25 05:50:28 +02:00
paulwer
74b7581354 allow hosted + enterprise 2024-06-25 05:48:16 +02:00
paulwer
a626736f2d feature flag 2024-06-24 17:40:27 +02:00
paulwer
a31e810ec9 fixes from tests 2024-06-24 16:30:00 +02:00
paulwer
4a56c114d0 Merge branch 'v5-develop' of https://github.com/invoiceninja/invoiceninja into feature-inbound-email-expenses 2024-06-24 14:38:38 +02:00
David Bomba
c315911da4 Payment float 2024-06-24 15:44:42 +10:00
David Bomba
3e760e6cc6 New payment flow 2024-06-24 14:38:53 +10:00
paulwer
371eb68856 remove old field data 2024-06-23 11:24:40 +02:00
paulwer
682d4883ff readd case 2024-06-23 09:36:54 +02:00
paulwer
e3da9914ba rework mindee limits 2024-06-23 09:32:51 +02:00
paulwer
aa12fe3976 wip mindee 2024-06-22 20:57:11 +02:00
paulwer
f480108c25 wip: adding mindee 2024-06-22 19:58:55 +02:00
paulwer
2a7eb83965 several reworks + wip mindee 2024-06-22 18:52:25 +02:00
paulwer
fc7d84dc24 minor fixes 2024-06-22 18:04:35 +02:00
paulwer
46f3fd3866 wrong implementation use each document for its own expense (or parse) 2024-06-22 17:55:07 +02:00
paulwer
d0cad92fce fix composer issue 2024-06-22 15:54:33 +02:00
paulwer
45e2b6aeb8 integrate ParseEDocument to InboundMailEngine 2024-06-22 15:33:53 +02:00
paulwer
e586455be3 rewrite EDocument service structure 2024-06-22 15:02:53 +02:00
paulwer
b13e54f49b Merge branch 'v5-develop' of https://github.com/invoiceninja/invoiceninja into feature-inbound-email-expenses 2024-06-22 14:20:04 +02:00
paulwer
cb4e348c15 Merge branch 'v5-develop' of https://github.com/invoiceninja/invoiceninja into feature-inbound-email-expenses 2024-06-16 13:30:09 +02:00
paulwer
e204788ef6 minor code cleanups 2024-05-22 07:14:53 +02:00
paulwer
8e850ea2a6 wip: ZugferdEDocument implementation 2024-05-22 07:07:27 +02:00
paulwer
befbdc399d Merge branch 'v5-develop' of https://github.com/invoiceninja/invoiceninja into feature-inbound-email-expenses 2024-05-21 06:50:47 +02:00
paulwer
22bc9425a2 fix: env for black and whitelist 2024-05-19 06:59:37 +02:00
paulwer
ef60992843 fix: reduce vars in favor for db 2024-05-19 06:55:15 +02:00
paulwer
9c9c4a998c Merge branch 'v5-develop' of https://github.com/invoiceninja/invoiceninja into feature-inbound-email-expenses 2024-05-19 06:46:54 +02:00
paulwer
e08e377b34 fixes: env vars 2024-05-19 06:31:26 +02:00
paulwer
96d4a250cf fixes on MultiDB 2024-04-24 08:56:53 +02:00
paulwer
8378f9c1d1 fixes 2024-04-24 08:49:02 +02:00
paulwer
21aa38c52f fix invalid fields in VendorTransformer 2024-04-24 08:44:28 +02:00
paulwer
5a5df06cda fix ninja.php 2024-04-24 08:42:38 +02:00
paulwer
b2110de110 replace Log::info with nlog 2024-04-24 08:40:58 +02:00
paulwer
f530d95f59 update composer 2024-04-23 22:40:43 +02:00
paulwer
2d091f3cb6 Merge branch 'v5-develop' of https://github.com/invoiceninja/invoiceninja into feature-inbound-email-expenses 2024-04-23 22:38:57 +02:00
paulwer
9aa97d7dda spelling mistake 2024-04-07 16:35:57 +02:00
paulwer
7b29ee8ebf remove unused variables from ExpenseMailbox check 2024-04-07 16:30:04 +02:00
paulwer
8547af74ab fixes 2024-04-07 16:26:35 +02:00
paulwer
c1ec89b0a7 fixes for spam-blocking 2024-04-07 16:08:34 +02:00
paulwer
4ac3289819 brevo fixes 2024-04-07 14:10:42 +02:00
paulwer
c02a4fb08d minor adjustment according spam behavior 2024-04-07 13:58:10 +02:00
paulwer
9a733f06c0 Merge branch 'v5-develop' of https://github.com/invoiceninja/invoiceninja into feature-inbound-email-expenses 2024-04-07 13:26:28 +02:00
paulwer
832397a98e minor security updates 2024-04-07 13:26:10 +02:00
paulwer
b7378b9b10 renaming inbound_mailbox to expense_mailbox 2024-04-04 07:27:07 +02:00
paulwer
b7a29bb2c7 fix: getVendor / getClient 2024-04-03 15:01:57 +02:00
paulwer
f0d61a8261 remove vendor email colums 2024-04-03 08:33:40 +02:00
paulwer
f0ba86b699 fixes 2024-04-03 08:20:36 +02:00
paulwer
8e1dc42bfb prevent downloading actions, when sender is blocked 2024-04-03 08:06:39 +02:00
paulwer
a1338cbbab fixes for postmark + inbound engine rework 2024-04-03 07:57:23 +02:00
paulwer
60861e0afa Merge branch 'v5-develop' of https://github.com/invoiceninja/invoiceninja into feature-inbound-email-expenses 2024-04-01 16:07:30 +02:00
paulwer
ab8d960384 drop imap support classes 2024-04-01 16:04:49 +02:00
paulwer
0983330187 minor fixes 2024-03-25 07:18:32 +01:00
paulwer
a1b35909b0 brevo webhook validation 2024-03-25 07:16:26 +01:00
paulwer
1db0350273 changes related to allow_clients 2024-03-25 07:08:41 +01:00
paulwer
157037f56f renamings + move imap job to self-hosted only + allow by clients 2024-03-25 06:41:22 +01:00
paulwer
91a048009a init postmark webhook 2024-03-24 21:53:17 +01:00
paulwer
e888cde7dd removing webhook soft-failes in favor for system logging 2024-03-24 13:32:52 +01:00
paulwer
d712191012 minor changes 2024-03-24 13:10:45 +01:00
paulwer
ad964ca61a Merge branch 'v5-develop' of https://github.com/invoiceninja/invoiceninja into feature-inbound-email-expenses 2024-03-24 12:54:55 +01:00
paulwer
2cbeb23d8f minor logging improvements 2024-03-24 12:51:24 +01:00
paulwer
8031f1c277 fixes for company blacklists and whitelists + system logs 2024-03-24 11:40:17 +01:00
paulwer
a6d09a2ce5 feat: global blacklist for specific emails 2024-03-24 11:00:29 +01:00
paulwer
f43909141f brevo webhook + better attachement fetching cycle + fixes for brevo key integration namings 2024-03-24 10:53:20 +01:00
paulwer
9792ab71dc minor changes 2024-03-19 13:09:03 +01:00
paulwer
f5dfedf8fa fixes 2024-03-19 13:05:12 +01:00
paulwer
16b46bc74d add mail from storage as example in programm-code 2024-03-19 13:02:51 +01:00
paulwer
73bcf928e4 updates mailgun webhook loading message data on runtime 2024-03-19 12:56:39 +01:00
paulwer
0aaaf27314 Merge branch 'v5-develop' of https://github.com/invoiceninja/invoiceninja into feature-inbound-email-expenses 2024-03-19 08:16:01 +01:00
paulwer
74fca7de2e comment 2024-03-19 08:10:18 +01:00
paulwer
a5b3215ff7 feat: company blacklist 2024-03-19 07:55:55 +01:00
paulwer
7cc5ff11d4 working ingres engine 2024-03-19 07:39:35 +01:00
paulwer
c80e3bf921 working mailgun inbound webhook 2024-03-18 08:04:54 +01:00
paulwer
2f4f547eed fixes 2024-03-17 09:14:19 +01:00
paulwer
21d569bd2b Merge branch 'v5-develop' of https://github.com/invoiceninja/invoiceninja into feature-inbound-email-expenses 2024-03-17 09:14:07 +01:00
paulwer
6bb86caff3 Merge branch 'v5-develop' of https://github.com/invoiceninja/invoiceninja into feature-inbound-email-expenses 2024-02-27 08:13:19 +01:00
paulwer
1d92b91fc6 merge cleanups 2024-01-20 08:53:47 +01:00
paulwer
678da384a9 Merge branch 'v5-develop' of https://github.com/invoiceninja/invoiceninja into feature-inbound-email-expenses 2024-01-20 08:51:09 +01:00
paulwer
b3986df788 remove mailbox preset 2023-12-28 10:53:15 +01:00
paulwer
3fc35aefe7 Merge branch 'v5-develop' of https://github.com/invoiceninja/invoiceninja into feature-inbound-email-expenses 2023-12-28 10:50:32 +01:00
paulwer
eea6c3458c remove unwanted lang 2023-12-28 10:29:35 +01:00
paulwer
ad009b5837 changes according to: https://github.com/invoiceninja/invoiceninja/pull/9042#discussion_r1432330656 2023-12-28 10:18:24 +01:00
paulwer
77a615adb6 minor updates 2023-12-28 10:05:46 +01:00
paulwer
21a8f4da76 rework env-struct & validation of expense_mailbox 2023-12-28 10:00:38 +01:00
paulwer
80a9d51ffb revert preseed mailboxes 2023-12-28 09:52:27 +01:00
paulwer
450569e5c4 ignore emails with no documents attached 2023-12-19 08:51:50 +01:00
paulwer
5efb33d1d3 minor changes 2023-12-18 17:28:36 +01:00
paulwer
08662c1595 renaming and minor changes 2023-12-18 17:24:59 +01:00
paulwer
7245de8c4c wip: spam protection 2023-12-18 17:21:15 +01:00
paulwer
5d70daaaaa wip: restruct and init IngresEmailEngine 2023-12-18 15:05:15 +01:00
paulwer
f0415b6b20 fixes 2023-12-16 18:13:26 +01:00
paulwer
8d43eb6664 better ExpenseMailboxJob 2023-12-16 18:13:08 +01:00
paulwer
9ef5a2501b fix composer 2023-12-16 17:21:52 +01:00
paulwer
ad480a5b32 fixes 2023-12-16 16:36:17 +01:00
paulwer
c393fdaa9b handling of temporary files + wip init of webhooks processing 2023-12-16 16:27:40 +01:00
paulwer
e05db36841 wip: first initial setup for creating expenses from webhooks 2023-12-16 09:17:25 +01:00
paulwer
0e24ac0a14 fixes 2023-12-15 18:36:49 +01:00
paulwer
168fef71c7 switch to endings for better oportunity to display in frontend 2023-12-15 18:36:17 +01:00
paulwer
36279be694 validator for ExpenseMailbox property 2023-12-15 18:15:55 +01:00
paulwer
dd9727a701 minor comments 2023-12-15 07:24:31 +01:00
paulwer
58a7456087 wip process normal mailgun webhooks 2023-12-15 07:22:24 +01:00
paulwer
6df213956f wip: updates 2023-12-14 19:17:29 +01:00
paulwer
5adb799100 removing pop3 integration, becasue we cannot move mails 2023-12-14 18:25:38 +01:00
paulwer
8d6925afd3 restruct files 2023-12-14 16:40:43 +01:00
paulwer
a6f9275144 save mailbox at company 2023-12-14 13:16:14 +01:00
paulwer
8bd9f34d98 vendor updates 2023-12-14 10:39:55 +01:00
paulwer
d8064a9a35 improv 2023-12-14 10:33:49 +01:00
paulwer
b065542020 env-config 2023-12-14 08:32:15 +01:00
paulwer
1125f57a7f init inbound webhook 2023-12-14 07:51:38 +01:00
paulwer
b2b1cce085 initial commit 2023-12-10 16:06:33 +01:00
1022 changed files with 389240 additions and 331387 deletions

View File

@ -24,6 +24,7 @@ QUEUE_CONNECTION=sync
SESSION_DRIVER=file
SESSION_LIFETIME=120
MAIL_MAILER=smtp
REDIS_HOST=127.0.0.1
REDIS_PASSWORD=null
REDIS_PORT=6379

View File

@ -8,7 +8,7 @@ assignees: ''
---
<!-- Before posting please check our "Troubleshooting" category in the docs:
https://invoiceninja.github.io/docs/self-host-troubleshooting/ -->
https://invoiceninja.github.io/en/self-host-troubleshooting/ -->
## Setup
- Version: <!-- i.e. v4.5.25 / v5.0.30 -->

View File

@ -18,7 +18,7 @@ jobs:
phpunit-versions: ['latest']
ci_node_total: [ 8 ]
ci_node_index: [ 0, 1, 2, 3, 4, 5, 6, 7]
laravel: [10.*]
laravel: [11.*]
dependency-version: [prefer-stable]
env:
@ -103,7 +103,6 @@ jobs:
restore-keys: |
${{ runner.os }}-${{ matrix.php }}-composer-
- name: Install composer dependencies
run: |
composer config -g github-oauth.github.com ${{ secrets.GITHUB_TOKEN }}

View File

@ -51,7 +51,9 @@ All Pro and Enterprise features from the hosted app are included in the open-sou
* [Docker File](https://hub.docker.com/r/invoiceninja/invoiceninja/)
* [Cloudron](https://www.cloudron.io/store/com.invoiceninja.cloudronapp2.html)
* [Softaculous](https://www.softaculous.com/apps/ecommerce/Invoice_Ninja)
* [Elestio](https://elest.io/open-source/invoiceninja)
* [YunoHost](https://apps.yunohost.org/app/invoiceninja5)
### Recommended Providers
* [Stripe](https://stripe.com/)
* [Postmark](https://postmarkapp.com/)

View File

@ -1 +1 @@
5.10.17
5.10.29

View File

@ -0,0 +1,50 @@
<?php
/**
* Invoice Ninja (https://invoiceninja.com).
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2021. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www.elastic.co/licensing/elastic-license
*/
namespace App\Casts;
use App\DataMapper\QuickbooksSettings;
use Illuminate\Contracts\Database\Eloquent\CastsAttributes;
class QuickbooksSettingsCast implements CastsAttributes
{
public function get($model, string $key, $value, array $attributes)
{
$data = json_decode($value, true);
if(!is_array($data))
return null;
$qb = new QuickbooksSettings();
$qb->accessTokenKey = $data['accessTokenKey'];
$qb->refresh_token = $data['refresh_token'];
$qb->realmID = $data['realmID'];
$qb->accessTokenExpiresAt = $data['accessTokenExpiresAt'];
$qb->refreshTokenExpiresAt = $data['refreshTokenExpiresAt'];
$qb->settings = $data['settings'] ?? [];
return $qb;
}
public function set($model, string $key, $value, array $attributes)
{
return [
$key => json_encode([
'accessTokenKey' => $value->accessTokenKey,
'refresh_token' => $value->refresh_token,
'realmID' => $value->realmID,
'accessTokenExpiresAt' => $value->accessTokenExpiresAt,
'refreshTokenExpiresAt' => $value->refreshTokenExpiresAt,
'settings' => $value->settings,
])
];
}
}

View File

@ -1169,10 +1169,10 @@ class CheckData extends Command
->whereNull('exchange_rate')
->orWhere('exchange_rate', 0)
->cursor()
->each(function ($expense){
->each(function ($expense) {
$expense->exchange_rate = 1;
$expense->saveQuietly();
$this->logMessage("Fixing - exchange rate for expense :: {$expense->id}");
});

View File

@ -1116,7 +1116,7 @@ class CreateSingleAccount extends Command
private function countryClients($company, $user)
{
Client::unguard();
Client::create([

View File

@ -67,7 +67,7 @@ class Kernel extends ConsoleKernel
/* Checks Rotessa Transactions */
$schedule->job(new TransactionReport())->dailyAt('01:48')->withoutOverlapping()->name('rotessa-transaction-report')->onOneServer();
/* Stale Invoice Cleanup*/
$schedule->job(new CleanStaleInvoiceOrder())->hourlyAt(30)->withoutOverlapping()->name('stale-invoice-job')->onOneServer();

View File

@ -0,0 +1,83 @@
<?php
/**
* Invoice Ninja (https://invoiceninja.com).
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2024. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www.elastic.co/licensing/elastic-license
*/
namespace App\DataMapper\Analytics;
use Turbo124\Beacon\ExampleMetric\GenericMixedMetric;
class LegalEntityCreated extends GenericMixedMetric
{
/**
* The type of Sample.
*
* Monotonically incrementing counter
*
* - counter
*
* @var string
*/
public $type = 'mixed_metric';
/**
* The name of the counter.
* @var string
*/
public $name = 'einvoice.legal_entity.created';
/**
* The datetime of the counter measurement.
*
* date("Y-m-d H:i:s")
*
*/
public $datetime;
/**
* The Class failure name
* set to 0.
*
* @var string
*/
public $string_metric5 = 'stub';
/**
* The exception string
* set to 0.
*
* @var string
*/
public $string_metric6 = 'stub';
/**
* The counter
* set to 1.
*
*/
public $int_metric1 = 1;
/**
* Company Key
* @var string
*/
public $string_metric7 = '';
/**
* Subject
* @var string
*/
public $string_metric8 = '';
public function __construct($string_metric7 = '', $string_metric8 = '')
{
$this->string_metric7 = $string_metric7;
$this->string_metric8 = $string_metric8;
}
}

View File

@ -16,13 +16,6 @@ namespace App\DataMapper;
*/
class BaseSettings
{
// //@deprecated
// public function __construct($obj)
// {
// // foreach ($obj as $key => $value) {
// // $obj->{$key} = $value;
// // }
// }
public static function setCasts($obj, $casts)
{

View File

@ -515,10 +515,14 @@ class CompanySettings extends BaseSettings
public $quote_schedule_reminder1 = ''; //before_valid_until_date,after_valid_until_date,after_quote_date
public $quote_late_fee_amount1 = 0;
public $quote_late_fee_percent1 = 0;
public string $payment_flow = 'default'; //smooth
public string $email_subject_payment_failed = '';
public string $email_template_payment_failed = '';
public static $casts = [
'payment_flow' => 'string',
'enable_quote_reminder1' => 'bool',
'quote_num_days_reminder1' => 'int',
'quote_schedule_reminder1' => 'string',
@ -768,6 +772,8 @@ class CompanySettings extends BaseSettings
'portal_custom_js' => 'string',
'client_portal_enable_uploads' => 'bool',
'purchase_order_number_counter' => 'integer',
'email_template_payment_failed' => 'string',
'email_subject_payment_failed' => 'string',
];
public static $free_plan_casts = [

View File

@ -30,6 +30,7 @@ class EmailTemplateDefaults
'email_template_custom2',
'email_template_custom3',
'email_template_purchase_order',
'email_template_payment_failed'
];
public static function getDefaultTemplate($template, $locale)
@ -39,6 +40,8 @@ class EmailTemplateDefaults
switch ($template) {
/* Template */
case 'email_template_payment_failed':
return self::emailPaymentFailedTemplate();
case 'email_template_invoice':
return self::emailInvoiceTemplate();
case 'email_template_quote':
@ -73,6 +76,9 @@ class EmailTemplateDefaults
case 'email_subject_invoice':
return self::emailInvoiceSubject();
case 'email_subject_payment_failed':
return self::emailPaymentFailedSubject();
case 'email_subject_quote':
return self::emailQuoteSubject();
@ -120,27 +126,35 @@ class EmailTemplateDefaults
case 'email_quote_subject_reminder1':
return self::emailQuoteReminder1Subject();
default:
return self::emailInvoiceTemplate();
}
}
public static function emailPaymentFailedSubject()
{
return ctrans('texts.notification_invoice_payment_failed_subject', ['invoice' => '$number']);
}
public static function emailPaymentFailedTemplate()
{
return '<p>$client<br><br>'.ctrans('texts.client_payment_failure_body', ['invoice' => '$number', 'amount' => '$amount']).'</p><div>$payment_error</div><br><div>$view_button</div>';
}
public static function emailQuoteReminder1Subject()
{
return ctrans('texts.quote_reminder_subject', ['quote' => '$number', 'company' => '$company.name']);
}
public static function emailQuoteReminder1Body()
{
$invoice_message = '<p>$client<br><br>'.self::transformText('quote_reminder_message').'</p><div class="center">$view_button</div>';
return $invoice_message;
return '<p>$client<br><br>'.self::transformText('quote_reminder_message').'</p><div>$view_button</div>';
}
public static function emailVendorNotificationSubject()
{
return self::transformText('vendor_notification_subject');
@ -163,14 +177,14 @@ class EmailTemplateDefaults
public static function emailInvoiceTemplate()
{
$invoice_message = '<p>$client<br><br>'.self::transformText('invoice_message').'</p><div class="center">$view_button</div>';
$invoice_message = '<p>$client<br><br>'.self::transformText('invoice_message').'</p><div>$view_button</div>';
return $invoice_message;
}
public static function emailInvoiceReminderTemplate()
{
$invoice_message = '<p>$client<br><br>'.self::transformText('reminder_message').'</p><div class="center">$view_button</div>';
$invoice_message = '<p>$client<br><br>'.self::transformText('reminder_message').'</p><div>$view_button</div>';
return $invoice_message;
}
@ -182,7 +196,7 @@ class EmailTemplateDefaults
public static function emailQuoteTemplate()
{
$quote_message = '<p>$client<br><br>'.self::transformText('quote_message').'</p><div class="center">$view_button</div>';
$quote_message = '<p>$client<br><br>'.self::transformText('quote_message').'</p><div>$view_button</div>';
return $quote_message;
}
@ -199,28 +213,28 @@ class EmailTemplateDefaults
public static function emailPurchaseOrderTemplate()
{
$purchase_order_message = '<p>$vendor<br><br>'.self::transformText('purchase_order_message').'</p><div class="center">$view_button</div>';
$purchase_order_message = '<p>$vendor<br><br>'.self::transformText('purchase_order_message').'</p><div>$view_button</div>';
return $purchase_order_message;
}
public static function emailPaymentTemplate()
{
$payment_message = '<p>$client<br><br>'.self::transformText('payment_message').'<br><br>$invoices</p><div class="center">$view_button</div>';
$payment_message = '<p>$client<br><br>'.self::transformText('payment_message').'<br><br>$invoices</p><div>$view_button</div>';
return $payment_message;
}
public static function emailCreditTemplate()
{
$credit_message = '<p>$client<br><br>'.self::transformText('credit_message').'</p><div class="center">$view_button</div>';
$credit_message = '<p>$client<br><br>'.self::transformText('credit_message').'</p><div>$view_button</div>';
return $credit_message;
}
public static function emailPaymentPartialTemplate()
{
$payment_message = '<p>$client<br><br>'.self::transformText('payment_message').'<br><br>$invoices</p><div class="center">$view_button</div>';
$payment_message = '<p>$client<br><br>'.self::transformText('payment_message').'<br><br>$invoices</p><div>$view_button</div>';
return $payment_message;
}

View File

@ -0,0 +1,61 @@
<?php
/**
* Invoice Ninja (https://invoiceninja.com).
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2024. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www.elastic.co/licensing/elastic-license
*/
namespace App\DataMapper;
use Illuminate\Contracts\Database\Eloquent\Castable;
use App\Casts\QuickbooksSettingsCast;
/**
* QuickbooksSettings.
*/
class QuickbooksSettings implements Castable
{
public string $accessTokenKey;
public string $refresh_token;
public string $realmID;
public int $accessTokenExpiresAt;
public int $refreshTokenExpiresAt;
public string $baseURL;
/**
* entity client,invoice,quote,purchase_order,vendor,payment
* sync true/false
* update_record true/false
* direction push/pull/birectional
* */
public array $settings = [
'client' => ['sync' => true, 'update_record' => true, 'direction' => 'bidirectional'],
'vendor' => ['sync' => true, 'update_record' => true, 'direction' => 'bidirectional'],
'invoice' => ['sync' => true, 'update_record' => true, 'direction' => 'bidirectional'],
'sales' => ['sync' => true, 'update_record' => true, 'direction' => 'bidirectional'],
'quote' => ['sync' => true, 'update_record' => true, 'direction' => 'bidirectional'],
'purchase_order' => ['sync' => true, 'update_record' => true, 'direction' => 'bidirectional'],
'product' => ['sync' => true, 'update_record' => true, 'direction' => 'bidirectional'],
'payment' => ['sync' => true, 'update_record' => true, 'direction' => 'bidirectional'],
];
/**
* Get the name of the caster class to use when casting from / to this cast target.
*
* @param array<string, mixed> $arguments
*/
public static function castUsing(array $arguments): string
{
return QuickbooksSettingsCast::class;
}
}

View File

@ -17,6 +17,7 @@ use App\Models\Invoice;
use App\Models\Product;
use App\DataProviders\USStates;
use App\DataMapper\Tax\ZipTax\Response;
use App\Models\RecurringInvoice;
class BaseRule implements RuleInterface
{
@ -47,6 +48,9 @@ class BaseRule implements RuleInterface
'DK', // Denmark
'EE', // Estonia
'ES', // Spain
'ES-CN', // Canary Islands
'ES-CE', // Ceuta
'ES-ML', // Melilla
'FI', // Finland
'FR', // France
'GR', // Greece
@ -77,6 +81,9 @@ class BaseRule implements RuleInterface
'DK' => 'EU', // Denmark
'EE' => 'EU', // Estonia
'ES' => 'EU', // Spain
'ES-CN' => 'EU', // Canary Islands
'ES-CE' => 'EU', // Ceuta
'ES-ML' => 'EU', // Melilla
'FI' => 'EU', // Finland
'FR' => 'EU', // France
'GR' => 'EU', // Greece
@ -132,7 +139,7 @@ class BaseRule implements RuleInterface
public function shouldCalcTax(): bool
{
return $this->should_calc_tax;
return $this->should_calc_tax && $this->checkIfInvoiceLocked();
}
/**
* Initializes the tax rule for the entity.
@ -215,7 +222,7 @@ class BaseRule implements RuleInterface
$this->invoice->tax_data = $tax_data;
if(\DB::transactionLevel() == 0) {
if(\DB::transactionLevel() == 0 && isset($this->invoice->id)) {
try {
$this->invoice->saveQuietly();
@ -400,4 +407,40 @@ class BaseRule implements RuleInterface
return ! in_array($iso_3166_2, array_merge($this->eu_country_codes, array_keys($this->region_codes)));
}
private function checkIfInvoiceLocked(): bool
{
$lock_invoices = $this->client->getSetting('lock_invoices');
if($this->invoice instanceof RecurringInvoice) {
return true;
}
switch ($lock_invoices) {
case 'off':
return true;
case 'when_sent':
if ($this->invoice->status_id == Invoice::STATUS_SENT) {
return false;
}
return true;
case 'when_paid':
if ($this->invoice->status_id == Invoice::STATUS_PAID) {
return false;
}
return true;
//if now is greater than the end of month the invoice was dated - do not modify
case 'end_of_month':
if(\Carbon\Carbon::parse($this->invoice->date)->setTimezone($this->invoice->company->timezone()->name)->endOfMonth()->lte(now())) {
return false;
}
return true;
default:
return true;
}
}
}

View File

@ -43,6 +43,8 @@ class Rule extends BaseRule implements RuleInterface
public float $reduced_tax_rate = 0;
public string $tax_name1 = 'MwSt.';
private string $tax_name;
/**
* Initializes the rules and builds any required data.
*
@ -50,6 +52,7 @@ class Rule extends BaseRule implements RuleInterface
*/
public function init(): self
{
$this->tax_name = $this->tax_name1;
$this->calculateRates();
return $this;
@ -91,6 +94,7 @@ class Rule extends BaseRule implements RuleInterface
*/
public function reverseTax($item): self
{
$this->tax_name1 = $this->tax_name;
$this->tax_rate1 = 0;
return $this;
@ -103,6 +107,8 @@ class Rule extends BaseRule implements RuleInterface
*/
public function taxReduced($item): self
{
$this->tax_name1 = $this->tax_name;
$this->tax_rate1 = $this->reduced_tax_rate;
return $this;
@ -115,6 +121,8 @@ class Rule extends BaseRule implements RuleInterface
*/
public function zeroRated($item): self
{
$this->tax_name1 = $this->tax_name;
$this->tax_rate1 = 0;
return $this;
@ -142,6 +150,7 @@ class Rule extends BaseRule implements RuleInterface
public function taxDigital($item): self
{
$this->tax_name1 = $this->tax_name;
$this->tax_rate1 = $this->tax_rate;
return $this;
@ -155,6 +164,7 @@ class Rule extends BaseRule implements RuleInterface
public function taxService($item): self
{
$this->tax_name1 = $this->tax_name;
$this->tax_rate1 = $this->tax_rate;
return $this;
@ -168,6 +178,7 @@ class Rule extends BaseRule implements RuleInterface
public function taxShipping($item): self
{
$this->tax_name1 = $this->tax_name;
$this->tax_rate1 = $this->tax_rate;
return $this;
@ -181,6 +192,7 @@ class Rule extends BaseRule implements RuleInterface
public function taxPhysical($item): self
{
$this->tax_name1 = $this->tax_name;
$this->tax_rate1 = $this->tax_rate;
return $this;
@ -229,8 +241,7 @@ class Rule extends BaseRule implements RuleInterface
// nlog("tax exempt");
$this->tax_rate = 0;
$this->reduced_tax_rate = 0;
} elseif($this->client_subregion != $this->client->company->tax_data->seller_subregion && in_array($this->client_subregion, $this->eu_country_codes) && $this->client->vat_number && $this->eu_business_tax_exempt) {
// elseif($this->client_subregion != $this->client->company->tax_data->seller_subregion && in_array($this->client_subregion, $this->eu_country_codes) && $this->client->has_valid_vat_number && $this->eu_business_tax_exempt)
} elseif($this->client_subregion != $this->client->company->tax_data->seller_subregion && in_array($this->client_subregion, $this->eu_country_codes) && $this->client->vat_number && $this->client->has_valid_vat_number && $this->eu_business_tax_exempt) {
// nlog("euro zone and tax exempt");
$this->tax_rate = 0;
$this->reduced_tax_rate = 0;
@ -240,8 +251,8 @@ class Rule extends BaseRule implements RuleInterface
$this->reduced_tax_rate = 0;
} elseif(!in_array($this->client_subregion, $this->eu_country_codes)) {
$this->defaultForeign();
} elseif(in_array($this->client_subregion, $this->eu_country_codes) && !$this->client->vat_number) { //eu country / no valid vat
if(($this->client->company->tax_data->seller_subregion != $this->client_subregion) && $this->client->company->tax_data->regions->EU->has_sales_above_threshold) {
} elseif(in_array($this->client_subregion, $this->eu_country_codes) && ((strlen($this->client->vat_number ?? '') == 1) || !$this->client->has_valid_vat_number)) { //eu country / no valid vat
if($this->client->company->tax_data->seller_subregion != $this->client_subregion) {
// nlog("eu zone with sales above threshold");
$this->tax_rate = $this->client->company->tax_data->regions->EU->subregions->{$this->client->country->iso_3166_2}->tax_rate ?? 0;
$this->reduced_tax_rate = $this->client->company->tax_data->regions->EU->subregions->{$this->client->country->iso_3166_2}->reduced_tax_rate ?? 0;

View File

@ -0,0 +1,44 @@
<?php
/**
* Invoice Ninja (https://invoiceninja.com).
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2024. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www.elastic.co/licensing/elastic-license
*/
namespace App\DataMapper\Tax\ES_CE;
use App\DataMapper\Tax\DE\Rule as DERule;
class Rule extends DERule
{
/** @var string $seller_region */
public string $seller_region = 'EU';
/** @var bool $consumer_tax_exempt */
public bool $consumer_tax_exempt = false;
/** @var bool $business_tax_exempt */
public bool $business_tax_exempt = false;
/** @var bool $eu_business_tax_exempt */
public bool $eu_business_tax_exempt = true;
/** @var bool $foreign_business_tax_exempt */
public bool $foreign_business_tax_exempt = false;
/** @var bool $foreign_consumer_tax_exempt */
public bool $foreign_consumer_tax_exempt = false;
/** @var float $tax_rate */
public float $tax_rate = 0;
/** @var float $reduced_tax_rate */
public float $reduced_tax_rate = 0;
public string $tax_name1 = 'IGIC';
}

View File

@ -0,0 +1,44 @@
<?php
/**
* Invoice Ninja (https://invoiceninja.com).
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2024. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www.elastic.co/licensing/elastic-license
*/
namespace App\DataMapper\Tax\ES_CN;
use App\DataMapper\Tax\DE\Rule as DERule;
class Rule extends DERule
{
/** @var string $seller_region */
public string $seller_region = 'EU';
/** @var bool $consumer_tax_exempt */
public bool $consumer_tax_exempt = false;
/** @var bool $business_tax_exempt */
public bool $business_tax_exempt = false;
/** @var bool $eu_business_tax_exempt */
public bool $eu_business_tax_exempt = true;
/** @var bool $foreign_business_tax_exempt */
public bool $foreign_business_tax_exempt = false;
/** @var bool $foreign_consumer_tax_exempt */
public bool $foreign_consumer_tax_exempt = false;
/** @var float $tax_rate */
public float $tax_rate = 0;
/** @var float $reduced_tax_rate */
public float $reduced_tax_rate = 0;
public string $tax_name1 = 'IGIC';
}

View File

@ -0,0 +1,44 @@
<?php
/**
* Invoice Ninja (https://invoiceninja.com).
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2024. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www.elastic.co/licensing/elastic-license
*/
namespace App\DataMapper\Tax\ES_ML;
use App\DataMapper\Tax\DE\Rule as DERule;
class Rule extends DERule
{
/** @var string $seller_region */
public string $seller_region = 'EU';
/** @var bool $consumer_tax_exempt */
public bool $consumer_tax_exempt = false;
/** @var bool $business_tax_exempt */
public bool $business_tax_exempt = false;
/** @var bool $eu_business_tax_exempt */
public bool $eu_business_tax_exempt = true;
/** @var bool $foreign_business_tax_exempt */
public bool $foreign_business_tax_exempt = false;
/** @var bool $foreign_consumer_tax_exempt */
public bool $foreign_consumer_tax_exempt = false;
/** @var float $tax_rate */
public float $tax_rate = 0;
/** @var float $reduced_tax_rate */
public float $reduced_tax_rate = 0;
public string $tax_name1 = 'IGIC';
}

View File

@ -17,7 +17,7 @@ class TaxModel
public string $seller_subregion = 'CA';
/** @var string $version */
public string $version = 'beta';
public string $version = 'gamma';
/** @var object $regions */
public object $regions;
@ -34,10 +34,10 @@ class TaxModel
if(!$model) {
$this->regions = $this->init();
} else {
//@phpstan-ignore-next-line
foreach($model as $key => $value) {
$this->{$key} = $value;
$this->{$key} = $value;
}
}
@ -48,8 +48,7 @@ class TaxModel
public function migrate(): self
{
if($this->version == 'alpha')
{
if($this->version == 'alpha') {
$this->regions->EU->subregions->PL = new \stdClass();
$this->regions->EU->subregions->PL->tax_rate = 23;
$this->regions->EU->subregions->PL->tax_name = 'VAT';
@ -59,6 +58,32 @@ class TaxModel
$this->version = 'beta';
}
if($this->version == 'beta') {
//CEUTA
$this->regions->EU->subregions->{'ES-CE'} = new \stdClass();
$this->regions->EU->subregions->{'ES-CE'}->tax_rate = 4;
$this->regions->EU->subregions->{'ES-CE'}->tax_name = 'IGIC';
$this->regions->EU->subregions->{'ES-CE'}->reduced_tax_rate = 4;
$this->regions->EU->subregions->{'ES-CE'}->apply_tax = false;
//MELILLA ML 4
$this->regions->EU->subregions->{'ES-ML'} = new \stdClass();
$this->regions->EU->subregions->{'ES-ML'}->tax_rate = 4;
$this->regions->EU->subregions->{'ES-ML'}->tax_name = 'IGIC';
$this->regions->EU->subregions->{'ES-ML'}->reduced_tax_rate = 4;
$this->regions->EU->subregions->{'ES-ML'}->apply_tax = false;
//CANARIAS CN 7/3
$this->regions->EU->subregions->{'ES-CN'} = new \stdClass();
$this->regions->EU->subregions->{'ES-CN'}->tax_rate = 7;
$this->regions->EU->subregions->{'ES-CN'}->tax_name = 'IGIC';
$this->regions->EU->subregions->{'ES-CN'}->reduced_tax_rate = 4;
$this->regions->EU->subregions->{'ES-CN'}->apply_tax = false;
$this->version = 'gamma';
}
return $this;
}
@ -420,6 +445,25 @@ class TaxModel
$this->regions->EU->subregions->ES->reduced_tax_rate = 10;
$this->regions->EU->subregions->ES->apply_tax = false;
$this->regions->EU->subregions->{'ES-CE'} = new \stdClass();
$this->regions->EU->subregions->{'ES-CE'}->tax_rate = 4;
$this->regions->EU->subregions->{'ES-CE'}->tax_name = 'IGIC';
$this->regions->EU->subregions->{'ES-CE'}->reduced_tax_rate = 4;
$this->regions->EU->subregions->{'ES-CE'}->apply_tax = false;
$this->regions->EU->subregions->{'ES-ML'} = new \stdClass();
$this->regions->EU->subregions->{'ES-ML'}->tax_rate = 4;
$this->regions->EU->subregions->{'ES-ML'}->tax_name = 'IGIC';
$this->regions->EU->subregions->{'ES-ML'}->reduced_tax_rate = 4;
$this->regions->EU->subregions->{'ES-ML'}->apply_tax = false;
$this->regions->EU->subregions->{'ES-CN'} = new \stdClass();
$this->regions->EU->subregions->{'ES-CN'}->tax_rate = 7;
$this->regions->EU->subregions->{'ES-CN'}->tax_name = 'IGIC';
$this->regions->EU->subregions->{'ES-CN'}->reduced_tax_rate = 3;
$this->regions->EU->subregions->{'ES-CN'}->apply_tax = false;
$this->regions->EU->subregions->FI = new \stdClass();
$this->regions->EU->subregions->FI->tax_rate = 24;
$this->regions->EU->subregions->FI->tax_name = 'ALV';

View File

@ -1,8 +1,18 @@
<?php
/**
* Invoice Ninja (https://invoiceninja.com).
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2024. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www.elastic.co/licensing/elastic-license
*/
namespace App\DataProviders;
final class CAProvinces {
final class CAProvinces
{
/**
* The provinces and territories of Canada
*
@ -30,7 +40,8 @@ final class CAProvinces {
* @param string $abbreviation
* @return string
*/
public static function getName($abbreviation) {
public static function getName($abbreviation)
{
return self::$provinces[$abbreviation];
}
@ -39,7 +50,8 @@ final class CAProvinces {
*
* @return array
*/
public static function get() {
public static function get()
{
return self::$provinces;
}
@ -49,7 +61,8 @@ final class CAProvinces {
* @param string $name
* @return string
*/
public static function getAbbreviation($name) {
public static function getAbbreviation($name)
{
return array_search(ucwords($name), self::$provinces);
}
}

View File

@ -1,19 +0,0 @@
<?php
namespace App\DataProviders;
use Omnipay\Rotessa\Object\Frequency;
final class Frequencies
{
public static function get() : array {
return Frequency::getTypes();
}
public static function getFromType() {
}
public static function getOnePayment() {
return Frequency::ONCE;
}
}

22
app/Enum/HttpVerb.php Normal file
View File

@ -0,0 +1,22 @@
<?php
/**
* Invoice Ninja (https://invoiceninja.com).
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2024. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www.elastic.co/licensing/elastic-license
*/
namespace App\Enum;
enum HttpVerb: string
{
case POST = 'post';
case PUT = 'put';
case GET = 'get';
case PATCH = 'patch';
case DELETE = 'delete';
}

View File

@ -58,7 +58,7 @@ class ClientWasArchived implements ShouldBroadcast
public function broadcastWith()
{
$manager = new Manager();
$manager->setSerializer(new ArraySerializer());
$class = sprintf('App\\Transformers\\%sTransformer', class_basename($this->client));
@ -79,7 +79,7 @@ class ClientWasArchived implements ShouldBroadcast
*/
public function broadcastOn()
{
return [
new PrivateChannel("company-{$this->company->company_key}"),
];

View File

@ -0,0 +1,35 @@
<?php
/**
* Invoice Ninja (https://invoiceninja.com).
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2024. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www.elastic.co/licensing/elastic-license
*/
namespace App\Events\Invoice;
use App\Models\Company;
use App\Models\Invoice;
use Illuminate\Queue\SerializesModels;
/**
* Class InvoiceAutoBillFailed.
*/
class InvoiceAutoBillFailed
{
use SerializesModels;
/**
* Create a new event instance.
*
* @param Invoice $invoice
* @param Company $company
* @param array $event_vars
*/
public function __construct(public Invoice $invoice, public Company $company, public array $event_vars, public ?string $notes)
{
}
}

View File

@ -0,0 +1,35 @@
<?php
/**
* Invoice Ninja (https://invoiceninja.com).
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2024. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www.elastic.co/licensing/elastic-license
*/
namespace App\Events\Invoice;
use App\Models\Company;
use App\Models\Invoice;
use Illuminate\Queue\SerializesModels;
/**
* Class InvoiceAutoBillSuccess.
*/
class InvoiceAutoBillSuccess
{
use SerializesModels;
/**
* Create a new event instance.
*
* @param Invoice $invoice
* @param Company $company
* @param array $event_vars
*/
public function __construct(public Invoice $invoice, public Company $company, public array $event_vars)
{
}
}

View File

@ -39,6 +39,6 @@ class DuplicatePaymentException extends Exception
return response()->json([
'message' => 'Duplicate request',
], 400);
}
}

View File

@ -0,0 +1,34 @@
<?php
/**
* Invoice Ninja (https://invoiceninja.com).
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2024. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www.elastic.co/licensing/elastic-license
*/
namespace App\Exceptions;
use Exception;
class PeppolValidationException extends Exception
{
protected string $field = '';
public function __construct($message, $field, $code = 0, Exception $previous = null)
{
// Store the custom data
$this->field = $field;
// Ensure that everything is assigned properly by calling the parent constructor
parent::__construct($message, $code, $previous);
}
public function getInvalidField()
{
return $this->field;
}
}

View File

@ -101,8 +101,11 @@ class ActivityExport extends BaseExport
$t = app('translator');
$t->replace(Ninja::transformTranslations($this->company->settings));
$this->date_format = DateFormat::find($this->company->settings->date_format_id)->format;
/** @var \App\Models\DateFormat $df */
$df = DateFormat::query()->find($this->company->settings->date_format_id);
$this->date_format = $df->format;
if (count($this->input['report_keys']) == 0) {
$this->input['report_keys'] = array_values($this->entity_keys);
}
@ -129,8 +132,8 @@ class ActivityExport extends BaseExport
$query->cursor()
->each(function ($entity) {
/** @var \App\Models\Activity $entity */
/** @var \App\Models\Activity $entity */
$this->buildRow($entity);
});

View File

@ -451,6 +451,7 @@ class BaseExport
'project' => 'task.project_id',
'billable' => 'task.billable',
'item_notes' => 'task.item_notes',
'time_log' => 'task.time_log',
];
protected array $forced_client_fields = [
@ -844,7 +845,7 @@ class BaseExport
/**
* Apply Product Filters
*
* @param Builder $query
* @param \Illuminate\Database\Eloquent\Builder $query
*
* @return Builder
*/
@ -869,7 +870,7 @@ class BaseExport
/**
* Add Client Filter
*
* @param Builder $query
* @param \Illuminate\Database\Eloquent\Builder $query
* @param mixed $clients
*
* @return Builder
@ -892,7 +893,7 @@ class BaseExport
/**
* Add Vendor Filter
*
* @param Builder $query
* @param \Illuminate\Database\Eloquent\Builder $query
* @param string $vendors
*
* @return Builder
@ -916,7 +917,7 @@ class BaseExport
/**
* AddProjectFilter
*
* @param Builder $query
* @param \Illuminate\Database\Eloquent\Builder $query
* @param string $projects
*
* @return Builder
@ -940,7 +941,7 @@ class BaseExport
/**
* Add Category Filter
*
* @param Builder $query
* @param \Illuminate\Database\Eloquent\Builder $query
* @param string $expense_categories
*
* @return Builder
@ -965,7 +966,7 @@ class BaseExport
/**
* Add Payment Status Filters
*
* @param Builder $query
* @param \Illuminate\Database\Eloquent\Builder $query
* @param string $status
*
* @return Builder
@ -1023,10 +1024,10 @@ class BaseExport
/**
* Add RecurringInvoice Status Filter
*
* @param Builder $query
* @param \Illuminate\Database\Eloquent\Builder $query
* @param string $status
*
* @return Builder
* @return \Illuminate\Database\Eloquent\Builder
*/
protected function addRecurringInvoiceStatusFilter(Builder $query, string $status): Builder
{
@ -1040,7 +1041,7 @@ class BaseExport
$recurring_filters = [];
if($this->company->getSetting('report_include_drafts')){
if($this->company->getSetting('report_include_drafts')) {
$recurring_filters[] = RecurringInvoice::STATUS_DRAFT;
}
@ -1066,7 +1067,7 @@ class BaseExport
/**
* Add QuoteStatus Filter
*
* @param Builder $query
* @param \Illuminate\Database\Eloquent\Builder $query
* @param string $status
*
* @return Builder
@ -1132,7 +1133,7 @@ class BaseExport
/**
* Add PurchaseOrder Status Filter
*
* @param Builder $query
* @param \Illuminate\Database\Eloquent\Builder $query
* @param string $status
*
* @return Builder
@ -1182,13 +1183,13 @@ class BaseExport
/**
* Add Invoice Status Filter
*
* @param Builder $query
* @param \Illuminate\Database\Eloquent\Builder $query
* @param string $status
* @return Builder
*/
protected function addInvoiceStatusFilter(Builder $query, string $status): Builder
{
/** @var array $status_parameters */
$status_parameters = explode(',', $status);
@ -1248,7 +1249,7 @@ class BaseExport
/**
* Add Date Range
*
* @param Builder $query
* @param \Illuminate\Database\Eloquent\Builder $query
* @param ?string $table_name
* @return Builder
*/
@ -1269,7 +1270,7 @@ class BaseExport
$custom_start_date = now()->startOfYear();
$custom_end_date = now();
}
switch ($date_range) {
case 'all':
$this->start_date = 'All available data';
@ -1615,10 +1616,10 @@ class BaseExport
ZipDocuments::dispatch($documents, $this->company, $user);
}
}
/**
* Tests that the column exists
* on the table prior to adding it to
* on the table prior to adding it to
* the query builder
*
* @param string $table

View File

@ -102,7 +102,7 @@ class ClientExport extends BaseExport
$report = $query->cursor()
->map(function ($client) {
/** @var \App\Models\Client $client */
$row = $this->buildRow($client);
return $this->processMetaData($row, $client);
@ -133,7 +133,7 @@ class ClientExport extends BaseExport
$query->where('is_deleted', 0);
}
$query = $this->addDateRange($query,' clients');
$query = $this->addDateRange($query, ' clients');
if($this->input['document_email_attachment'] ?? false) {
$this->queueDocuments($query);
@ -156,8 +156,8 @@ class ClientExport extends BaseExport
$query->cursor()
->each(function ($client) {
/** @var \App\Models\Client $client */
/** @var \App\Models\Client $client */
$this->csv->insertOne($this->buildRow($client));
});

View File

@ -52,7 +52,7 @@ class CreditExport extends BaseExport
$report = $query->cursor()
->map(function ($credit) {
/** @var \App\Models\Credit $credit */
$row = $this->buildRow($credit);
return $this->processMetaData($row, $credit);

View File

@ -54,7 +54,7 @@ class DocumentExport extends BaseExport
$report = $query->cursor()
->map(function ($document) {
/** @var \App\Models\Document $document */
$row = $this->buildRow($document);
return $this->processMetaData($row, $document);
@ -101,7 +101,7 @@ class DocumentExport extends BaseExport
$query->cursor()
->each(function ($entity) {
/** @var mixed $entity */
/** @var mixed $entity */
$this->csv->insertOne($this->buildRow($entity));
});

View File

@ -52,7 +52,7 @@ class ExpenseExport extends BaseExport
$report = $query->cursor()
->map(function ($resource) {
/** @var \App\Models\Expense $resource */
$row = $this->buildRow($resource);
return $this->processMetaData($row, $resource);
@ -134,7 +134,7 @@ class ExpenseExport extends BaseExport
$query->cursor()
->each(function ($expense) {
/** @var \App\Models\Expense $expense */
$this->csv->insertOne($this->buildRow($expense));
});
@ -266,11 +266,10 @@ class ExpenseExport extends BaseExport
if($expense->calculate_tax_by_amount) {
$total_tax_amount = round($expense->tax_amount1 + $expense->tax_amount2 + $expense->tax_amount3, $precision);
if($expense->uses_inclusive_taxes) {
$entity['expense.net_amount'] = round($expense->amount, $precision) - $total_tax_amount;
}
else {
} else {
$entity['expense.net_amount'] = round($expense->amount, $precision);
}

View File

@ -99,7 +99,7 @@ class InvoiceExport extends BaseExport
$report = $query->cursor()
->map(function ($resource) {
/** @var \App\Models\Invoice $resource */
$row = $this->buildRow($resource);
return $this->processMetaData($row, $resource);
@ -121,7 +121,7 @@ class InvoiceExport extends BaseExport
$query->cursor()
->each(function ($invoice) {
/** @var \App\Models\Invoice $invoice */
$this->csv->insertOne($this->buildRow($invoice));
});

View File

@ -113,7 +113,7 @@ class InvoiceItemExport extends BaseExport
$query->cursor()
->each(function ($resource) {
/** @var \App\Models\Invoice $resource */
$this->iterateItems($resource);
@ -143,7 +143,7 @@ class InvoiceItemExport extends BaseExport
$query->cursor()
->each(function ($invoice) {
/** @var \App\Models\Invoice $invoice */
$this->iterateItems($invoice);
});
@ -229,10 +229,6 @@ class InvoiceItemExport extends BaseExport
// $entity['currency'] = $invoice->client->currency() ? $invoice->client->currency()->code : $invoice->company->currency()->code;
// }
// if(array_key_exists('type', $entity)) {
// $entity['type'] = $invoice->typeIdString($entity['type']);
// }
// if(array_key_exists('tax_category', $entity)) {
// $entity['tax_category'] = $invoice->taxTypeString($entity['tax_category']);
// }
@ -266,9 +262,9 @@ class InvoiceItemExport extends BaseExport
}
if (in_array('invoice.project', $this->input['report_keys'])) {
$entity['invoice.project'] = $invoice->project ? $invoice->project->name : '';// @phpstan-ignore-line
$entity['invoice.project'] = $invoice->project ? $invoice->project->name : '';// @phpstan-ignore-line
}
return $entity;
}

View File

@ -92,7 +92,7 @@ class PaymentExport extends BaseExport
$report = $query->cursor()
->map(function ($resource) {
/** @var \App\Models\Payment $resource */
$row = $this->buildRow($resource);
return $this->processMetaData($row, $resource);
@ -114,8 +114,8 @@ class PaymentExport extends BaseExport
$query->cursor()
->each(function ($entity) {
/** @var \App\Models\Payment $entity */
/** @var \App\Models\Payment $entity */
$this->csv->insertOne($this->buildRow($entity));
});

View File

@ -51,7 +51,7 @@ class ProductExport extends BaseExport
$report = $query->cursor()
->map(function ($resource) {
/** @var \App\Models\Product $resource */
$row = $this->buildRow($resource);
return $this->processMetaData($row, $resource);
@ -106,8 +106,8 @@ class ProductExport extends BaseExport
$query->cursor()
->each(function ($entity) {
/** @var \App\Models\Product $entity */
$this->csv->insertOne($this->buildRow($entity));
/** @var \App\Models\Product $entity */
$this->csv->insertOne($this->buildRow($entity));
});
return $this->csv->toString();

View File

@ -98,7 +98,7 @@ class PurchaseOrderExport extends BaseExport
$report = $query->cursor()
->map(function ($resource) {
/** @var \App\Models\PurchaseOrder $resource */
$row = $this->buildRow($resource);
return $this->processMetaData($row, $resource);
@ -121,9 +121,9 @@ class PurchaseOrderExport extends BaseExport
$query->cursor()
->each(function ($purchase_order) {
/** @var \App\Models\PurchaseOrder $purchase_order */
$this->csv->insertOne($this->buildRow($purchase_order));
/** @var \App\Models\PurchaseOrder $purchase_order */
$this->csv->insertOne($this->buildRow($purchase_order));
});
return $this->csv->toString();

View File

@ -101,15 +101,15 @@ class PurchaseOrderItemExport extends BaseExport
$query->cursor()
->each(function ($resource) {
/** @var \App\Models\PurchaseOrder $resource */
$this->iterateItems($resource);
foreach($this->storage_array as $row) {
$this->storage_item_array[] = $this->processItemMetaData($row, $resource);
}
/** @var \App\Models\PurchaseOrder $resource */
$this->iterateItems($resource);
$this->storage_array = [];
foreach($this->storage_array as $row) {
$this->storage_item_array[] = $this->processItemMetaData($row, $resource);
}
$this->storage_array = [];
});
@ -129,9 +129,9 @@ class PurchaseOrderItemExport extends BaseExport
$query->cursor()
->each(function ($purchase_order) {
/** @var \App\Models\PurchaseOrder $purchase_order */
$this->iterateItems($purchase_order);
/** @var \App\Models\PurchaseOrder $purchase_order */
$this->iterateItems($purchase_order);
});
$this->csv->insertAll($this->storage_array);
@ -213,10 +213,6 @@ class PurchaseOrderItemExport extends BaseExport
// $entity['currency'] = $purchase_order->vendor->currency() ? $purchase_order->vendor->currency()->code : $purchase_order->company->currency()->code;
// }
// if(array_key_exists('type', $entity)) {
// $entity['type'] = $purchase_order->typeIdString($entity['type']);
// }
// if(array_key_exists('tax_category', $entity)) {
// $entity['tax_category'] = $purchase_order->taxTypeString($entity['tax_category']);
// }

View File

@ -127,7 +127,7 @@ class QuoteExport extends BaseExport
$query->cursor()
->each(function ($quote) {
/** @var \App\Models\Quote $quote */
$this->csv->insertOne($this->buildRow($quote));
});

View File

@ -104,7 +104,7 @@ class QuoteItemExport extends BaseExport
$query->cursor()
->each(function ($resource) {
/** @var \App\Models\Quote $resource */
$this->iterateItems($resource);
@ -136,7 +136,7 @@ class QuoteItemExport extends BaseExport
$query->cursor()
->each(function ($quote) {
/** @var \App\Models\Quote $quote */
$this->iterateItems($quote);
});

View File

@ -93,7 +93,7 @@ class RecurringInvoiceExport extends BaseExport
$query->cursor()
->each(function ($invoice) {
/** @var \App\Models\RecurringInvoice $invoice */
$this->csv->insertOne($this->buildRow($invoice));
});
@ -114,7 +114,7 @@ class RecurringInvoiceExport extends BaseExport
$report = $query->cursor()
->map(function ($resource) {
/** @var \App\Models\RecurringInvoice $resource */
$row = $this->buildRow($resource);
return $this->processMetaData($row, $resource);

View File

@ -106,9 +106,9 @@ class TaskExport extends BaseExport
$query->cursor()
->each(function ($entity) {
/** @var \App\Models\Task $entity*/
$this->buildRow($entity);
/** @var \App\Models\Task $entity*/
$this->buildRow($entity);
});
$this->csv->insertAll($this->storage_array);
@ -156,7 +156,7 @@ class TaskExport extends BaseExport
$entity[$key] = $transformed_entity[$parts[1]];
} elseif (array_key_exists($key, $transformed_entity)) {
$entity[$key] = $transformed_entity[$key];
} elseif (in_array($key, ['task.start_date', 'task.end_date', 'task.duration', 'task.billable', 'task.item_notes'])) {
} elseif (in_array($key, ['task.start_date', 'task.end_date', 'task.duration', 'task.billable', 'task.item_notes', 'task.time_log'])) {
$entity[$key] = '';
} else {
$entity[$key] = $this->decorator->transform($key, $task);
@ -207,6 +207,9 @@ class TaskExport extends BaseExport
$seconds = $task->calcDuration();
$entity['task.duration'] = $seconds;
$entity['task.duration_words'] = $seconds > 86400 ? CarbonInterval::seconds($seconds)->locale($this->company->locale())->cascade()->forHumans() : now()->startOfDay()->addSeconds($seconds)->format('H:i:s');
$entity['task.time_log'] = (isset($item[1]) && $item[1] != 0) ? $item[1] - $item[0] : ctrans('texts.is_running');
}
if (in_array('task.billable', $this->input['report_keys']) || in_array('billable', $this->input['report_keys'])) {

View File

@ -90,7 +90,7 @@ class VendorExport extends BaseExport
$report = $query->cursor()
->map(function ($resource) {
/** @var \App\Models\Vendor $resource */
$row = $this->buildRow($resource);
return $this->processMetaData($row, $resource);
@ -109,9 +109,9 @@ class VendorExport extends BaseExport
$query->cursor()
->each(function ($vendor) {
/** @var \App\Models\Vendor $vendor */
$this->csv->insertOne($this->buildRow($vendor));
/** @var \App\Models\Vendor $vendor */
$this->csv->insertOne($this->buildRow($vendor));
});
return $this->csv->toString();

View File

@ -96,7 +96,7 @@ class TaskDecorator extends Decorator implements DecoratorInterface
return '';
}
/**
* billable
*
@ -106,7 +106,7 @@ class TaskDecorator extends Decorator implements DecoratorInterface
{
return '';
}
/**
* items_notes
* @todo
@ -115,7 +115,7 @@ class TaskDecorator extends Decorator implements DecoratorInterface
{
return '';
}
public function duration(Task $task)
{
return $task->calcDuration();

View File

@ -16,7 +16,7 @@ use App\Models\Credit;
class CreditFactory
{
public static function create(int $company_id, int $user_id, object $settings = null, Client $client = null): Credit
public static function create(int $company_id, int $user_id): Credit
{
$credit = new Credit();
$credit->status_id = Credit::STATUS_DRAFT;

View File

@ -76,6 +76,26 @@ class InvoiceItemFactory
$data[] = $item;
}
$item = self::create();
$item->quantity = $faker->numberBetween(1, 10);
$item->cost = $faker->randomFloat(2, 1, 1000);
$item->line_total = $item->quantity * $item->cost;
$item->is_amount_discount = true;
$item->discount = $faker->numberBetween(1, 10);
$item->notes = str_replace(['"',"'"], ['',""], $faker->realText(20));
$item->product_key = $faker->word();
// $item->custom_value1 = $faker->realText(10);
// $item->custom_value2 = $faker->realText(10);
// $item->custom_value3 = $faker->realText(10);
// $item->custom_value4 = $faker->realText(10);
$item->tax_name1 = 'GST';
$item->tax_rate1 = 10.00;
$item->type_id = '2';
$data[] = $item;
return $data;
}

View File

@ -149,43 +149,43 @@ class RecurringExpenseToExpenseFactory
}
// if (Str::contains($match, '|')) {
$parts = explode('|', $match); // [ '[MONTH', 'MONTH+2]' ]
$parts = explode('|', $match); // [ '[MONTH', 'MONTH+2]' ]
$left = substr($parts[0], 1); // 'MONTH'
$right = substr($parts[1], 0, -1); // MONTH+2
$left = substr($parts[0], 1); // 'MONTH'
$right = substr($parts[1], 0, -1); // MONTH+2
// If left side is not part of replacements, skip.
if (! array_key_exists($left, $replacements['ranges'])) {
continue;
}
// If left side is not part of replacements, skip.
if (! array_key_exists($left, $replacements['ranges'])) {
continue;
}
$_left = Carbon::createFromDate(now()->year, now()->month)->translatedFormat('F Y');
$_right = '';
$_left = Carbon::createFromDate(now()->year, now()->month)->translatedFormat('F Y');
$_right = '';
// If right side doesn't have any calculations, replace with raw ranges keyword.
if (! Str::contains($right, ['-', '+', '/', '*'])) {
$_right = Carbon::createFromDate(now()->year, now()->month)->translatedFormat('F Y');
}
// If right side doesn't have any calculations, replace with raw ranges keyword.
if (! Str::contains($right, ['-', '+', '/', '*'])) {
$_right = Carbon::createFromDate(now()->year, now()->month)->translatedFormat('F Y');
}
// If right side contains one of math operations, calculate.
if (Str::contains($right, ['+'])) {
$operation = preg_match_all('/(?!^-)[+*\/-](\s?-)?/', $right, $_matches);
// If right side contains one of math operations, calculate.
if (Str::contains($right, ['+'])) {
$operation = preg_match_all('/(?!^-)[+*\/-](\s?-)?/', $right, $_matches);
$_operation = array_shift($_matches)[0]; // + -
$_operation = array_shift($_matches)[0]; // + -
$_value = explode($_operation, $right); // [MONTHYEAR, 4]
$_value = explode($_operation, $right); // [MONTHYEAR, 4]
$_right = Carbon::createFromDate(now()->year, now()->month)->addMonths($_value[1])->translatedFormat('F Y'); //@phpstan-ignore-line
}
$_right = Carbon::createFromDate(now()->year, now()->month)->addMonths($_value[1])->translatedFormat('F Y'); //@phpstan-ignore-line
}
$replacement = sprintf('%s to %s', $_left, $_right);
$replacement = sprintf('%s to %s', $_left, $_right);
$value = preg_replace(
sprintf('/%s/', preg_quote($match)),
$replacement,
$value,
1
);
$value = preg_replace(
sprintf('/%s/', preg_quote($match)),
$replacement,
$value,
1
);
// }
}

View File

@ -68,7 +68,7 @@ class BankTransactionFilters extends QueryFilters
*/
public function client_status(string $value = ''): Builder
{
if (strlen($value) == 0) {
if (strlen($value ?? '') == 0) {
return $this->builder;
}
@ -108,13 +108,24 @@ class BankTransactionFilters extends QueryFilters
}
if (count($debit_or_withdrawal_array) >= 1) {
$query->orWhereIn('base_type', $debit_or_withdrawal_array);
$query->whereIn('base_type', $debit_or_withdrawal_array);
}
});
return $this->builder;
}
public function active_banks(string $value = ''): Builder
{
if (strlen($value) == 0 || $value != 'true') {
return $this->builder;
}
return $this->builder->whereHas('bank_integration', function ($query){
$query->where('is_deleted', 0)->whereNull('deleted_at');
});
}
/**
* Filters the list based on Bank Accounts.

View File

@ -98,7 +98,14 @@ class CreditFilters extends QueryFilters
->orWhere('last_name', 'like', '%'.$filter.'%')
->orWhere('email', 'like', '%'.$filter.'%');
})
->orWhereRaw("JSON_UNQUOTE(JSON_EXTRACT(line_items, '$[*].notes')) LIKE ?", ['%'.$filter.'%']);
->orWhereRaw("
JSON_UNQUOTE(JSON_EXTRACT(
JSON_ARRAY(
JSON_UNQUOTE(JSON_EXTRACT(line_items, '$[*].notes')),
JSON_UNQUOTE(JSON_EXTRACT(line_items, '$[*].product_key'))
), '$[*]')
) LIKE ?", ['%'.$filter.'%']);
// ->orWhereRaw("JSON_UNQUOTE(JSON_EXTRACT(line_items, '$[*].notes')) LIKE ?", ['%'.$filter.'%']);
});
}

View File

@ -99,6 +99,12 @@ class ExpenseFilters extends QueryFilters
});
}
if (in_array('uninvoiced', $status_parameters)) {
$query->orWhere(function ($query) {
$query->whereNull('invoice_id');
});
}
if (in_array('paid', $status_parameters)) {
$query->orWhere(function ($query) {
$query->whereNotNull('payment_date');
@ -158,6 +164,19 @@ class ExpenseFilters extends QueryFilters
return $this->builder;
}
public function categories(string $categories = ''): Builder
{
$categories_exploded = explode(",", $categories);
if(empty($categories) || count(array_filter($categories_exploded)) == 0) {
return $this->builder;
}
$categories_keys = $this->transformKeys($categories_exploded);
return $this->builder->whereIn('category_id', $categories_keys);
}
public function number(string $number = ''): Builder
{
if (strlen($number) == 0) {
@ -205,6 +224,11 @@ class ExpenseFilters extends QueryFilters
->whereColumn('expense_categories.id', 'expenses.category_id'), $sort_col[1]);
}
if ($sort_col[0] == 'payment_date' && in_array($sort_col[1], ['asc', 'desc'])) {
return $this->builder
->orderByRaw('ISNULL(payment_date), payment_date '. $sort_col[1]);
}
if($sort_col[0] == 'number') {
return $this->builder->orderByRaw("REGEXP_REPLACE(number,'[^0-9]+','')+0 " . $dir);
}

View File

@ -125,7 +125,14 @@ class InvoiceFilters extends QueryFilters
->orWhere('last_name', 'like', '%'.$filter.'%')
->orWhere('email', 'like', '%'.$filter.'%');
})
->orWhereRaw("JSON_UNQUOTE(JSON_EXTRACT(line_items, '$[*].notes')) LIKE ?", ['%'.$filter.'%']);
->orWhereRaw("
JSON_UNQUOTE(JSON_EXTRACT(
JSON_ARRAY(
JSON_UNQUOTE(JSON_EXTRACT(line_items, '$[*].notes')),
JSON_UNQUOTE(JSON_EXTRACT(line_items, '$[*].product_key'))
), '$[*]')
) LIKE ?", ['%'.$filter.'%']);
// ->orWhereRaw("JSON_UNQUOTE(JSON_EXTRACT(line_items, '$[*].notes')) LIKE ?", ['%'.$filter.'%']);
});
}
@ -259,58 +266,6 @@ class InvoiceFilters extends QueryFilters
return $this->builder->where('due_date', '>=', $date);
}
/**
* Filter by date range
*
* @param string $date_range
* @return Builder
*/
public function date_range(string $date_range = ''): Builder
{
$parts = explode(",", $date_range);
if (count($parts) != 2) {
return $this->builder;
}
try {
$start_date = Carbon::parse($parts[0]);
$end_date = Carbon::parse($parts[1]);
return $this->builder->whereBetween('date', [$start_date, $end_date]);
} catch(\Exception $e) {
return $this->builder;
}
}
/**
* Filter by due date range
*
* @param string $date_range
* @return Builder
*/
public function due_date_range(string $date_range = ''): Builder
{
$parts = explode(",", $date_range);
if (count($parts) != 2) {
return $this->builder;
}
try {
$start_date = Carbon::parse($parts[0]);
$end_date = Carbon::parse($parts[1]);
return $this->builder->whereBetween('due_date', [$start_date, $end_date]);
} catch(\Exception $e) {
return $this->builder;
}
}
/**
* Sorts the list based on $sort.
*

View File

@ -60,7 +60,7 @@ class ProjectFilters extends QueryFilters
{
$sort_col = explode('|', $sort);
if (!is_array($sort_col) || count($sort_col) != 2) {
if (!is_array($sort_col) || count($sort_col) != 2 || !in_array($sort_col[0], \Illuminate\Support\Facades\Schema::getColumnListing('projects'))) {
return $this->builder;
}

View File

@ -96,7 +96,14 @@ class PurchaseOrderFilters extends QueryFilters
->orWhere('custom_value4', 'like', '%'.$filter.'%')
->orWhereHas('vendor', function ($q) use ($filter) {
$q->where('name', 'like', '%'.$filter.'%');
});
})
->orWhereRaw("
JSON_UNQUOTE(JSON_EXTRACT(
JSON_ARRAY(
JSON_UNQUOTE(JSON_EXTRACT(line_items, '$[*].notes')),
JSON_UNQUOTE(JSON_EXTRACT(line_items, '$[*].product_key'))
), '$[*]')
) LIKE ?", ['%'.$filter.'%']);
});
}

View File

@ -331,4 +331,61 @@ abstract class QueryFilters
->orderByRaw("{$this->with_property} = ? DESC", [$value])
->company();
}
/**
* Filter by date range
*
* @param string $date_range
* @return Builder
*/
public function date_range(string $date_range = ''): Builder
{
$parts = explode(",", $date_range);
if (count($parts) != 2 || !in_array('date', \Illuminate\Support\Facades\Schema::getColumnListing($this->builder->getModel()->getTable()))) {
return $this->builder;
}
try {
$start_date = Carbon::parse($parts[0]);
$end_date = Carbon::parse($parts[1]);
return $this->builder->whereBetween('date', [$start_date, $end_date]);
} catch(\Exception $e) {
return $this->builder;
}
}
/**
* Filter by due date range
*
* @param string $date_range
* @return Builder
*/
public function due_date_range(string $date_range = ''): Builder
{
$parts = explode(",", $date_range);
if (count($parts) != 2 || !in_array('due_date', \Illuminate\Support\Facades\Schema::getColumnListing($this->builder->getModel()->getTable()))) {
return $this->builder;
}
try {
$start_date = Carbon::parse($parts[0]);
$end_date = Carbon::parse($parts[1]);
return $this->builder->whereBetween('due_date', [$start_date, $end_date]);
} catch(\Exception $e) {
return $this->builder;
}
}
}

View File

@ -46,7 +46,14 @@ class QuoteFilters extends QueryFilters
->orWhere('last_name', 'like', '%'.$filter.'%')
->orWhere('email', 'like', '%'.$filter.'%');
})
->orWhereRaw("JSON_UNQUOTE(JSON_EXTRACT(line_items, '$[*].notes')) LIKE ?", ['%'.$filter.'%']);
->orWhereRaw("
JSON_UNQUOTE(JSON_EXTRACT(
JSON_ARRAY(
JSON_UNQUOTE(JSON_EXTRACT(line_items, '$[*].notes')),
JSON_UNQUOTE(JSON_EXTRACT(line_items, '$[*].product_key'))
), '$[*]')
) LIKE ?", ['%'.$filter.'%']);
// ->orWhereRaw("JSON_UNQUOTE(JSON_EXTRACT(line_items, '$[*].notes')) LIKE ?", ['%'.$filter.'%']);
});
}

View File

@ -49,7 +49,14 @@ class RecurringInvoiceFilters extends QueryFilters
->orWhere('last_name', 'like', '%'.$filter.'%')
->orWhere('email', 'like', '%'.$filter.'%');
})
->orWhereRaw("JSON_UNQUOTE(JSON_EXTRACT(line_items, '$[*].notes')) LIKE ?", ['%'.$filter.'%']);
->orWhereRaw("
JSON_UNQUOTE(JSON_EXTRACT(
JSON_ARRAY(
JSON_UNQUOTE(JSON_EXTRACT(line_items, '$[*].notes')),
JSON_UNQUOTE(JSON_EXTRACT(line_items, '$[*].product_key'))
), '$[*]')
) LIKE ?", ['%'.$filter.'%']);
//->orWhereRaw("JSON_UNQUOTE(JSON_EXTRACT(line_items, '$[*].notes')) LIKE ?", ['%'.$filter.'%']);
});
}
@ -134,7 +141,7 @@ class RecurringInvoiceFilters extends QueryFilters
return $this->builder->orderByRaw("REGEXP_REPLACE(number,'[^0-9]+','')+0 " . $dir);
}
if($sort_col[0] == 'status_id'){
if($sort_col[0] == 'status_id') {
return $this->builder->orderBy('status_id', $dir)->orderBy('last_sent_date', $dir);
}

View File

@ -85,6 +85,10 @@ class TaskFilters extends QueryFilters
$this->builder->whereNull('invoice_id');
}
if (in_array('is_running', $status_parameters)) {
$this->builder->where('is_running', true);
}
return $this->builder;
}

View File

@ -99,11 +99,12 @@ class TransactionTransformer implements BankRevenueInterface
} elseif (array_key_exists('internalTransactionId', $transaction)) {
$transactionId = $transaction["internalTransactionId"];
} else {
nlog(`Invalid Input for nordigen transaction transformer: ` . $transaction);
nlog('Invalid Input for nordigen transaction transformer: ' . $transaction);
throw new \Exception('invalid dataset: missing transactionId - Please report this error to the developer');
}
$amount = (float) $transaction["transactionAmount"]["amount"];
$base_type = $amount < 0 ? 'DEBIT' : 'CREDIT';
// description could be in varios places
$description = '';
@ -140,7 +141,7 @@ class TransactionTransformer implements BankRevenueInterface
return [
'transaction_id' => 0,
'nordigen_transaction_id' => $transactionId,
'amount' => $amount,
'amount' => abs($amount),
'currency_id' => $this->convertCurrency($transaction["transactionAmount"]["currency"]),
'category_id' => null,
'category_type' => array_key_exists('additionalInformation', $transaction) ? $transaction["additionalInformation"] : '',
@ -148,7 +149,7 @@ class TransactionTransformer implements BankRevenueInterface
'description' => $description,
'participant' => $participant,
'participant_name' => $participant_name,
'base_type' => $amount < 0 ? 'DEBIT' : 'CREDIT',
'base_type' => $base_type,
];
}
@ -165,7 +166,7 @@ class TransactionTransformer implements BankRevenueInterface
/** @var \App\Models\Currency $currency */
return $currency ? $currency->id : 1; //@phpstan-ignore-line
}
private function formatDate(string $input)

View File

@ -61,7 +61,7 @@ class EpcQrGenerator
} catch(\Throwable $e) {
nlog("EPC QR failure => ".$e->getMessage());
return '';
}
}
}

View File

@ -42,6 +42,9 @@ class InvoiceItemSum
'DK', // Denmark
'EE', // Estonia
'ES', // Spain
'ES-CE',
'ES-CN',
'ES-ML',
'FI', // Finland
'FR', // France
'GR', // Greece
@ -72,6 +75,9 @@ class InvoiceItemSum
'DK', // Denmark
'EE', // Estonia
'ES', // Spain
'ES-CE',
'ES-CN',
'ES-ML',
'FI', // Finland
'FR', // France
'GR', // Greece
@ -182,7 +188,7 @@ class InvoiceItemSum
/** @var \App\DataMapper\Tax\BaseRule $class */
$class = "App\DataMapper\Tax\\".$this->client->company->country()->iso_3166_2."\\Rule";
$class = "App\DataMapper\Tax\\".str_replace("-","_",$this->client->company->country()->iso_3166_2)."\\Rule";
$this->rule = new $class();

View File

@ -64,7 +64,7 @@ class InvoiceSumInclusive
{
$this->invoice = $invoice;
$this->client = $invoice->client ?? $invoice->vendor;
$this->precision = $this->client->currency()->precision;
$this->rappen_rounding = $this->client->getSetting('enable_rappen_rounding');

View File

@ -23,12 +23,12 @@ class ProRata
* the time interval and the frequency duration
*
* @param float $amount
* @param Carbon $from_date
* @param Carbon $to_date
* @param \Illuminate\Support\Carbon | \Carbon\Carbon $from_date
* @param \Illuminate\Support\Carbon | \Carbon\Carbon $to_date
* @param int $frequency
* @return float
*/
public function refund(float $amount, Carbon $from_date, Carbon $to_date, int $frequency): float
public function refund(float $amount, $from_date, $to_date, int $frequency): float
{
$days = intval(abs($from_date->copy()->diffInDays($to_date)));
$days_in_frequency = $this->getDaysInFrequency($frequency);
@ -41,12 +41,12 @@ class ProRata
* the time interval and the frequency duration
*
* @param float $amount
* @param Carbon $from_date
* @param Carbon $to_date
* @param \Illuminate\Support\Carbon | \Carbon\Carbon $from_date
* @param \Illuminate\Support\Carbon | \Carbon\Carbon $to_date
* @param int $frequency
* @return float
*/
public function charge(float $amount, Carbon $from_date, Carbon $to_date, int $frequency): float
public function charge(float $amount, $from_date, $to_date, int $frequency): float
{
$days = intval(abs($from_date->copy()->diffInDays($to_date)));
$days_in_frequency = $this->getDaysInFrequency($frequency);

View File

@ -53,7 +53,7 @@ class GmailTransport extends AbstractTransport
if ($bccs) {
$bcc_list = 'Bcc: ';
foreach ($bccs->getAddresses() as $address) {
foreach ($bccs->getAddresses() as $address) {
$bcc_list .= $address->getAddress() .',';
}

28
app/Helpers/Sanitizer.php Normal file
View File

@ -0,0 +1,28 @@
<?php
/**
* Invoice Ninja (https://invoiceninja.com).
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2024. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www.elastic.co/licensing/elastic-license
*/
namespace App\Helpers;
class Sanitizer
{
public static function removeBlanks($input): array
{
foreach ($input as &$value) {
if (is_array($value)) {
// Recursively apply the filter to nested arrays
$value = self::removeBlanks($value);
}
}
// Use array_filter to remove empty or null values
return array_filter($input);
}
}

View File

@ -22,5 +22,5 @@
*/
function ctrans(string $string, $replace = [], $locale = null): string
{
return trans($string, $replace, $locale);
return html_entity_decode(trans($string, $replace, $locale));
}

View File

@ -117,7 +117,7 @@ class ActivityController extends BaseController
}
/**
* downloadHistoricalEntity
*
@ -204,7 +204,7 @@ class ActivityController extends BaseController
$activity->user_id = $user->id;
$activity->ip = $request->ip();
$activity->activity_type_id = Activity::USER_NOTE;
switch (get_class($entity)) {
case Invoice::class:
$activity->invoice_id = $entity->id;
@ -254,17 +254,20 @@ class ActivityController extends BaseController
$activity->client_id = $entity->client_id;
$activity->project_id = $entity->project_id;
$activity->vendor_id = $entity->vendor_id;
// no break
case Task::class:
$activity->task_id = $entity->id;
$activity->expense_id = $entity->id;
$activity->client_id = $entity->client_id;
$activity->project_id = $entity->project_id;
$activity->vendor_id = $entity->vendor_id;
// no break
case Payment::class:
$activity->payment_id = $entity->id;
$activity->expense_id = $entity->id;
$activity->client_id = $entity->client_id;
$activity->project_id = $entity->project_id;
// no break
default:
# code...
break;

View File

@ -41,9 +41,10 @@ class ContactLoginController extends Controller
$company = false;
$account = false;
if($request->query('intended'))
if($request->query('intended')) {
$request->session()->put('url.intended', $request->query('intended'));
}
if ($request->session()->has('company_key')) {
MultiDB::findAndSetDbByCompanyKey($request->session()->get('company_key'));
$company = Company::where('company_key', $request->session()->get('company_key'))->first();
@ -141,9 +142,10 @@ class ContactLoginController extends Controller
}
$this->setRedirectPath();
if($intended)
if($intended) {
$this->redirectTo = $intended;
}
return $request->wantsJson()
? new JsonResponse([], 204)

View File

@ -399,8 +399,8 @@ class LoginController extends BaseController
$truth->setCompany($set_company);
//21-03-2024
$cu->each(function ($cu) {
/** @var \App\Models\CompanyUser $cu */
if(CompanyToken::query()->where('company_id', $cu->company_id)->where('user_id', $cu->user_id)->where('is_system', true)->doesntExist()) {

View File

@ -217,7 +217,7 @@ class BankIntegrationController extends BaseController
}
if (config('ninja.nordigen.secret_id') && config('ninja.nordigen.secret_key') && (Ninja::isSelfHost() || (Ninja::isHosted() && $user_account->isEnterprisePaidClient()))) {
$user_account->bank_integrations->where("integration_type", BankIntegration::INTEGRATION_TYPE_NORDIGEN)->each(function ($bank_integration) {
$user_account->bank_integrations->where("integration_type", BankIntegration::INTEGRATION_TYPE_NORDIGEN)->each(function ($bank_integration) {
/** @var \App\Models\BankIntegration $bank_integration */
ProcessBankTransactionsNordigen::dispatch($bank_integration);
});

View File

@ -934,7 +934,7 @@ class BaseController extends Controller
} elseif (in_array($this->entity_type, [Design::class, GroupSetting::class, PaymentTerm::class, TaskStatus::class])) {
// nlog($this->entity_type);
} else {
$query->where(function ($q) use ($user){ //grouping these together improves query performance significantly)
$query->where(function ($q) use ($user) { //grouping these together improves query performance significantly)
$q->where('user_id', '=', $user->id)->orWhere('assigned_user_id', $user->id);
});
}
@ -996,7 +996,7 @@ class BaseController extends Controller
if(request()->has('einvoice')) {
if(class_exists(Schema::class)){
if(class_exists(Schema::class)) {
$ro = new Schema();
$response_data['einvoice_schema'] = $ro('Peppol');
}

View File

@ -11,6 +11,7 @@
namespace App\Http\Controllers;
use App\Jobs\Brevo\ProcessBrevoInboundWebhook;
use App\Jobs\Brevo\ProcessBrevoWebhook;
use Illuminate\Http\Request;
@ -19,20 +20,19 @@ use Illuminate\Http\Request;
*/
class BrevoController extends BaseController
{
public function __construct()
{
}
/**
* Process Postmark Webhook.
* Process Brevo Webhook.
*
*
* @OA\Post(
* path="/api/v1/postmark_webhook",
* operationId="postmarkWebhook",
* tags={"postmark"},
* summary="Processing webhooks from PostMark",
* path="/api/v1/brevo_webhook",
* operationId="brevoWebhook",
* tags={"brevo"},
* summary="Processing webhooks from Brevo",
* description="Adds an credit to the system",
* @OA\Parameter(ref="#/components/parameters/X-API-TOKEN"),
* @OA\Parameter(ref="#/components/parameters/X-Requested-With"),
@ -60,12 +60,150 @@ class BrevoController extends BaseController
*/
public function webhook(Request $request)
{
if ($request->has('token') && $request->get('token') == config('services.brevo.key')) {
ProcessBrevoWebhook::dispatch($request->all())->delay(10);
if ($request->has('token') && $request->get('token') == config('services.brevo.secret')) {
ProcessBrevoWebhook::dispatch($request->all())->delay(rand(2, 10));
return response()->json(['message' => 'Success'], 200);
}
return response()->json(['message' => 'Unauthorized'], 403);
}
/**
* Process Brevo Inbound Webhook.
*
* IMPORTANT NOTICE: brevo strips old sended emails, therefore only current attachements are present
*
* IMPORTANT NOTICE: brevo saves the message and attachemnts for later retrieval, therefore we can process it within a async job for performance reasons
*
* @OA\Post(
* path="/api/v1/brevo_inbound_webhook",
* operationId="brevoInboundWebhook",
* tags={"brevo"},
* summary="Processing inbound webhooks from Brevo",
* description="Adds an credit to the system",
* @OA\Parameter(ref="#/components/parameters/X-API-TOKEN"),
* @OA\Parameter(ref="#/components/parameters/X-Requested-With"),
* @OA\Parameter(ref="#/components/parameters/include"),
* @OA\Response(
* response=200,
* description="Returns the saved credit object",
* @OA\Header(header="X-MINIMUM-CLIENT-VERSION", ref="#/components/headers/X-MINIMUM-CLIENT-VERSION"),
* @OA\Header(header="X-RateLimit-Remaining", ref="#/components/headers/X-RateLimit-Remaining"),
* @OA\Header(header="X-RateLimit-Limit", ref="#/components/headers/X-RateLimit-Limit"),
* @OA\JsonContent(ref="#/components/schemas/Credit"),
* ),
* @OA\Response(
* response=422,
* description="Validation error",
* @OA\JsonContent(ref="#/components/schemas/ValidationError"),
*
* ),
* @OA\Response(
* response="default",
* description="Unexpected Error",
* @OA\JsonContent(ref="#/components/schemas/Error"),
* ),
* )
*
* array (
* 'items' =>
* array (
* 0 =>
* array (
* 'Uuid' =>
* array (
* 0 => 'd9f48d52-a344-42a4-9056-9733488d9fa3',
* ),
* 'Recipients' =>
* array (
* 0 => 'test@test.de',
* ),
* 'MessageId' => '<CADfEuNvumhUdqAUa0j6MxzVp0ooMYqdb_KZ7nZqHNAfdDqwWEQ@mail.gmail.com>',
* 'InReplyTo' => NULL,
* 'From' =>
* array (
* 'Name' => 'Max Mustermann',
* 'Address' => 'max@mustermann.de',
* ),
* 'To' =>
* array (
* 0 =>
* array (
* 'Name' => NULL,
* 'Address' => 'test@test.de',
* ),
* ),
* 'Cc' =>
* array (
* ),
* 'Bcc' =>
* array (
* ),
* 'ReplyTo' => NULL,
* 'SentAtDate' => 'Sat, 23 Mar 2024 18:18:20 +0100',
* 'Subject' => 'TEST',
* 'Attachments' =>
* array (
* 0 =>
* array (
* 'Name' => 'flag--sv-1x1.svg',
* 'ContentType' => 'image/svg+xml',
* 'ContentLength' => 79957,
* 'ContentID' => 'f_lu4ct6s20',
* 'DownloadToken' => 'eyJmb2xkZXIiOiIyMDI0MDMyMzE3MTgzNi45OS43OTgwMDM4MDQiLCJmaWxlbmFtZSI6ImZsYWctLXN2LTF4MS5zdmcifQ',
* ),
* ),
* 'Headers' =>
* array (
* 'Received' => 'by mail-ed1-f51.google.com with SMTP id 4fb4d7f45d1cf-56b0af675deso3877288a12.1 for <test@test.de>; Sat, 23 Mar 2024 10:18:36 -0700 (PDT)',
* 'DKIM-Signature' => 'v=1; a=rsa-sha256; c=relaxed/relaxed; d=mustermann.de; s=google; t=1711214316; x=1711819116; darn=test.de; h=to:subject:message-id:date:from:mime-version:from:to:cc:subject :date:message-id:reply-to; bh=eBSl5M0zvmTd+dFXGXMMSWrQ4nCvUdyVx+1Xpl+YuX8=; b=ackw3d+qTvZk4JKxomvH626MvfwmH23mikOUc2hWwYiO6unmQgPs2w5spnkmD9aCZ9 G+3nPSYKntugOmqWstZH3z4B063U4Y6j5hTc19WtCyyb9UR+XD+C6L10yc6ez8QUhlZT uAGqDoJ+E8+dBxiMul2pow19lC88t3QxRXU+i8zScniV7SFkwzziCEODaB61yI0DXsZB bUkx5Gx6cztKaNVF2QgguF2nQnJFUnD2nabVFsihyJ5r6y61rkSM/YTfMJuES772lnhv IeF+vwiFNEPKafrchce6YJcvo5Vd5lYFK4LtHyCy3mwJpX2QY+WnWAfferZ2YfgEL0Sf K3Pw==',
* 'X-Google-DKIM-Signature' => 'v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1711214316; x=1711819116; h=to:subject:message-id:date:from:mime-version:x-gm-message-state :from:to:cc:subject:date:message-id:reply-to; bh=eBSl5M0zvmTd+dFXGXMMSWrQ4nCvUdyVx+1Xpl+YuX8=; b=fg4tXZnstRBexYlC6MD7C7is0kQj+xY66cSJ78tSa7PtSFQzY0zajDMsepMCGiiWmN /Pc/tRtk53pru/OtfzRT9pbM6mhM1arIt+QaQBQGU5xZVV5JXfPmdnPzXqAbQztyeHrk UcEkz+qDN3JNoidw2dJhhdt5MxdKssR572NwtBrn/rN7f1o/ThWzEz+P0o06GVBpxVYP wM0EkvcJj2SUOcn36kmp1ccbMUwYCU2h1JmniEFY8RTqu2il13iXoBvG4YPxe0c0hJ6z zw1N5rONeQM113N1rpbQzS1QLSngczuOhN24M3TOwrHJIec/BxrOW6KWl/uPUqiZAf65 f0tg==',
* 'X-Gm-Message-State' => 'AOJu0YzKhR1HY1oUXoq++LLpl6UOz1S60NfPxuPXBLcP+6aACYle8rqQ fYHe2rQYTpg4KWiOswu858STOW8qmiewXD6gH/LbmEFs7sknRyDPNr/+L0cv828A3o+SOvXu3uP SY6H1aNSwIpqTRhJ+nNjTuSUpuSoABd9fYXFwPuivV0DtBhoVmpE=',
* 'X-Google-Smtp-Source' => 'AGHT+IHdA9ZhW0dQxgOYx2OXBGmu4pzSR/zwJ0vcPNXFSqttKCPS2oTw1a9b2mMdhyUeoRAwP5TmhHlAtqUUrOPwkgg=',
* 'X-Received' => 'by 2002:a50:d74c:0:b0:567:3c07:8bbc with SMTP id i12-20020a50d74c000000b005673c078bbcmr2126401edj.21.1711214316135; Sat, 23 Mar 2024 10:18:36 -0700 (PDT)',
* 'MIME-Version' => '1.0',
* 'From' => 'Max Mustermann <max@mustermann.de>',
* 'Date' => 'Sat, 23 Mar 2024 18:18:20 +0100',
* 'Message-ID' => '<CADfEuNvumhUdqAUa0j6MxzVp0ooMYqdb_KZ7nZqHNAfdDqwWEQ@mail.gmail.com>',
* 'Subject' => 'TEST',
* 'To' => 'test@test.de',
* 'Content-Type' => 'multipart/mixed',
* ),
* 'SpamScore' => 2.8,
* 'ExtractedMarkdownMessage' => 'TEST',
* 'ExtractedMarkdownSignature' => NULL,
* 'RawHtmlBody' => '<div dir="ltr">TEST</div>',
* 'RawTextBody' => 'TEST',
* 'EMLDownloadToken' => 'eyJmb2xkZXIiOiIyMDI0MDMyMzE3MTgzNi45OS43OTgwMDM4MDQiLCJmaWxlbmFtZSI6InNtdHAuZW1sIn0',
* ),
* ),
* )
*/
public function inboundWebhook(Request $request)
{
$input = $request->all();
if (!($request->has('token') && $request->get('token') == config('ninja.inbound_mailbox.inbound_webhook_token')))
return response()->json(['message' => 'Unauthorized'], 403);
if (!array_key_exists('items', $input)) {
nlog('Failed: Message could not be parsed, because required parameters are missing.');
return response()->json(['message' => 'Failed. Invalid Parameters.'], 400);
}
foreach ($input["items"] as $item) {
if (!array_key_exists('Recipients', $item) || !array_key_exists('MessageId', $item)) {
nlog('Failed: Message could not be parsed, because required parameters are missing. At least one item was invalid.');
return response()->json(['message' => 'Failed. Invalid Parameters. At least one item was invalid.'], 400);
}
ProcessBrevoInboundWebhook::dispatch($item)->delay(rand(2, 10));
}
return response()->json(['message' => 'Success'], 201);
}
}

View File

@ -73,7 +73,7 @@ class ChartController extends BaseController
$user = auth()->user();
$cs = new ChartService($user->company(), $user, $user->isAdmin());
$result = $cs->getCalculatedField($request->all());
return response()->json($result, 200);
}

View File

@ -114,9 +114,10 @@ class InvitationController extends Controller
'invitation_key' => $invitation_key
]);
}
if(!auth()->guard('contact')->check()){
if(!auth()->guard('contact')->check()) {
$this->middleware('auth:contact');
/** @var \App\Models\InvoiceInvitation | \App\Models\QuoteInvitation | \App\Models\CreditInvitation | \App\Models\RecurringInvoiceInvitation $invitation */
return redirect()->route('client.login', ['intended' => route('client.'.$entity.'.show', [$entity => $this->encodePrimaryKey($invitation->{$key}), 'silent' => $is_silent])]);
}
@ -146,7 +147,7 @@ class InvitationController extends Controller
}
private function fireEntityViewedEvent($invitation, $entity_string)
{
switch ($entity_string) {

View File

@ -62,6 +62,7 @@ class InvoiceController extends Controller
$invitation = $invoice->invitations()->where('client_contact_id', auth()->guard('contact')->user()->id)->first();
// @phpstan-ignore-next-line
if ($invitation && auth()->guard('contact') && ! session()->get('is_silent') && ! $invitation->viewed_date) {
$invitation->markViewed();
@ -77,13 +78,20 @@ class InvoiceController extends Controller
'key' => $invitation ? $invitation->key : false,
'hash' => $hash,
'variables' => $variables,
'invoices' => [$invoice->hashed_id],
'db' => $invoice->company->db,
];
if ($request->query('mode') === 'fullscreen') {
return render('invoices.show-fullscreen', $data);
}
return $this->render('invoices.show', $data);
if(!$invoice->isPayable())
return $this->render('invoices.show',$data);
return auth()->guard('contact')->user()->client->getSetting('payment_flow') == 'default' ? $this->render('invoices.show', $data) : $this->render('invoices.show_smooth', $data);
// return $this->render('invoices.show_smooth', $data);
}
public function showBlob($hash)
@ -235,9 +243,12 @@ class InvoiceController extends Controller
'hashed_ids' => $invoices->pluck('hashed_id'),
'total' => $total,
'variables' => $variables,
'invitation' => $invitation,
'db' => $invitation->company->db,
];
return $this->render('invoices.payment', $data);
// return $this->render('invoices.payment', $data);
return auth()->guard('contact')->user()->client->getSetting('payment_flow') === 'default' ? $this->render('invoices.payment', $data) : $this->render('invoices.show_smooth_multi', $data);
}
/**

View File

@ -88,6 +88,8 @@ class NinjaPlanController extends Controller
{
$trial_started = "Trial Started @ ".now()->format('Y-m-d H:i:s');
auth()->guard('contact')->user()->fill($request->only(['first_name','last_name']))->save();
$client = auth()->guard('contact')->user()->client;
$client->private_notes = $trial_started;
$client->fill($request->all());

View File

@ -108,12 +108,6 @@ class PaymentController extends Controller
*/
public function process(Request $request)
{
// $request->validate([
// 'contact_first_name' => ['required'],
// 'contact_last_name' => ['required'],
// 'contact_email' => ['required', 'email'],
// ]);
return (new InstantPayment($request))->run();
}
@ -123,13 +117,7 @@ class PaymentController extends Controller
$gateway = CompanyGateway::findOrFail($request->input('company_gateway_id'));
$payment_hash = PaymentHash::with('fee_invoice')->where('hash', $request->payment_hash)->firstOrFail();
// if($payment_hash)
$invoice = $payment_hash->fee_invoice;
// else
// $invoice = Invoice::with('client')->where('id',$payment_hash->fee_invoice_id)->orderBy('id','desc')->first();
// $invoice = Invoice::with('client')->find($payment_hash->fee_invoice_id);
$client = $invoice ? $invoice->client : auth()->guard('contact')->user()->client;

View File

@ -56,8 +56,8 @@ class PaymentMethodController extends Controller
$data['gateway'] = $gateway;
/** @var \App\Models\ClientContact auth()->user() **/
$client_contact = auth()->user();
/** @var \App\Models\ClientContact auth()->guard('contact')->user() **/
$client_contact = auth()->guard('contact')->user();
$data['client'] = $client_contact->client;
return $gateway
@ -77,8 +77,8 @@ class PaymentMethodController extends Controller
{
$gateway = $this->getClientGateway();
/** @var \App\Models\ClientContact auth()->user() **/
$client_contact = auth()->user();
/** @var \App\Models\ClientContact auth()->guard('contact')->user() **/
$client_contact = auth()->guard('contact')->user();
return $gateway
->driver($client_contact->client)
@ -103,8 +103,8 @@ class PaymentMethodController extends Controller
public function verify(ClientGatewayToken $payment_method)
{
/** @var \App\Models\ClientContact auth()->user() **/
$client_contact = auth()->user();
/** @var \App\Models\ClientContact auth()->guard('contact')->user() **/
$client_contact = auth()->guard('contact')->user();
return $payment_method->gateway
->driver($client_contact->client)
@ -114,8 +114,8 @@ class PaymentMethodController extends Controller
public function processVerification(Request $request, ClientGatewaytoken $payment_method)
{
/** @var \App\Models\ClientContact auth()->user() **/
$client_contact = auth()->user();
/** @var \App\Models\ClientContact auth()->guard('contact')->user() **/
$client_contact = auth()->guard('contact')->user();
return $payment_method->gateway
->driver($client_contact->client)
@ -131,8 +131,8 @@ class PaymentMethodController extends Controller
*/
public function destroy(ClientGatewayToken $payment_method)
{
/** @var \App\Models\ClientContact auth()->user() **/
$client_contact = auth()->user();
/** @var \App\Models\ClientContact auth()->guard('contact')->user() **/
$client_contact = auth()->guard('contact')->user();
if ($payment_method->gateway()->exists()) {
$payment_method->gateway
@ -145,9 +145,19 @@ class PaymentMethodController extends Controller
event(new MethodDeleted($payment_method, auth()->guard('contact')->user()->company, Ninja::eventVars(auth()->guard('contact')->user()->id)));
$payment_method->is_deleted = true;
$payment_method->is_default = false;
$payment_method->delete();
$payment_method->save();
$def_cgt = auth()->guard('contact')->user()->client->gateway_tokens()->orderBy('id','desc')->first();
if($def_cgt)
{
$def_cgt->is_default = true;
$def_cgt->save();
}
} catch (Exception $e) {
nlog($e->getMessage());
@ -161,8 +171,8 @@ class PaymentMethodController extends Controller
private function getClientGateway()
{
/** @var \App\Models\ClientContact auth()->user() **/
$client_contact = auth()->user();
/** @var \App\Models\ClientContact auth()->guard('contact')->user() **/
$client_contact = auth()->guard('contact')->user();
if (request()->query('method') == GatewayType::CREDIT_CARD) {
return $client_contact->client->getCreditCardGateway();

View File

@ -35,11 +35,16 @@ class PrePaymentController extends Controller
/**
* Show the list of payments.
*
* @return Factory|View
* @return Factory|View|\Illuminate\Http\RedirectResponse
*/
public function index()
{
$client = auth()->guard('contact')->user()->client;
if(!$client->getSetting('client_initiated_payments'))
return redirect()->route('client.dashboard');
$minimum = $client->getSetting('client_initiated_payments_minimum');
$minimum_amount = $minimum == 0 ? "" : Number::formatMoney($minimum, $client);

View File

@ -94,7 +94,7 @@ class SubscriptionPurchaseController extends Controller
*/
private function setLocale(string $locale): string
{
/** @var \Illuminate\Support\Collection<\App\Models\Language> */
$languages = app('languages');
@ -104,6 +104,6 @@ class SubscriptionPurchaseController extends Controller
});
return $record ? $record->locale : 'en';
}
}

View File

@ -707,7 +707,7 @@ class CompanyController extends BaseController
}
/**
*
*
*
* @return \Symfony\Component\HttpFoundation\StreamedResponse | \Illuminate\Http\JsonResponse
*/

View File

@ -615,7 +615,7 @@ class CreditController extends BaseController
return response()->streamDownload(function () use ($file) {
echo $file;
}, $credit->numberFormatter() . '.pdf', ['Content-Type' => 'application/pdf']);
case 'archive':
$this->credit_repository->archive($credit);

View File

@ -150,6 +150,10 @@ class DocumentController extends BaseController
$document->fill($request->all());
$document->save();
if($document->documentable) { //@phpstan-ignore-line
$document->documentable->touch();
}
return $this->itemResponse($document->fresh());
}

View File

@ -0,0 +1,26 @@
<?php
/**
* Invoice Ninja (https://invoiceninja.com).
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2024. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www.elastic.co/licensing/elastic-license
*/
namespace App\Http\Controllers\EInvoice;
use App\Http\Controllers\Controller;
use App\Http\Requests\EInvoice\SignupRequest;
class SelfhostController extends Controller
{
public function index(SignupRequest $request)
{
return view('einvoice.index');
}
}

View File

@ -0,0 +1,39 @@
<?php
/**
* Invoice Ninja (https://invoiceninja.com).
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2024. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www.elastic.co/licensing/elastic-license
*/
namespace App\Http\Controllers;
use App\Http\Requests\EInvoice\ValidateEInvoiceRequest;
use App\Services\EDocument\Standards\Validation\Peppol\EntityLevel;
class EInvoiceController extends BaseController
{
public function validateEntity(ValidateEInvoiceRequest $request)
{
$el = new EntityLevel();
$data = [];
match($request->entity){
'invoices' => $data = $el->checkInvoice($request->getEntity()),
'clients' => $data = $el->checkClient($request->getEntity()),
'companies' => $data = $el->checkCompany($request->getEntity()),
default => $data['passes'] = false,
};
nlog($data);
return response()->json($data, $data['passes'] ? 200 : 400);
}
}

View File

@ -51,9 +51,9 @@ class EmailHistoryController extends BaseController
/** @var \App\Models\User $user */
$user = auth()->user();
$data = SystemLog::where('company_id', $user->company()->id)
->where('category_id', SystemLog::CATEGORY_MAIL)
->whereJsonContains('log->history->entity', $request->entity)
->whereJsonContains('log->history->entity_id', $this->encodePrimaryKey($request->entity_id))
->orderBy('id', 'DESC')
->cursor()

View File

@ -497,7 +497,7 @@ class ExpenseController extends BaseController
$expenses = Expense::withTrashed()->find($request->ids);
if($request->action == 'bulk_categorize' && $user->can('edit', $expenses->first())) {
if ($request->action == 'bulk_categorize' && $user->can('edit', $expenses->first())) {
$this->expense_repo->categorize($expenses, $request->category_id);
$expenses = collect([]);
}
@ -573,7 +573,7 @@ class ExpenseController extends BaseController
*/
public function upload(UploadExpenseRequest $request, Expense $expense)
{
if (! $this->checkFeature(Account::FEATURE_DOCUMENTS)) {
if (!$this->checkFeature(Account::FEATURE_DOCUMENTS)) {
return $this->featureFailure();
}
@ -584,14 +584,60 @@ class ExpenseController extends BaseController
return $this->itemResponse($expense->fresh());
}
public function edocument(EDocumentRequest $request): string
/**
* @OA\Post(
* path="/api/v1/expenses/edocument",
* operationId="edocumentExpense",
* tags={"expenses"},
* summary="Uploads an electronic document to a expense",
* description="Handles the uploading of an electronic document to a expense",
* @OA\Parameter(ref="#/components/parameters/X-API-TOKEN"),
* @OA\Parameter(ref="#/components/parameters/X-Requested-With"),
* @OA\Parameter(ref="#/components/parameters/include"),
* @OA\RequestBody(
* description="User credentials",
* required=true,
* @OA\MediaType(
* mediaType="multipart/form-data",
* @OA\Schema(
* type="array",
* @OA\Items(
* type="string",
* format="binary",
* description="The files to be uploaded",
* ),
* )
* )
* ),
* @OA\Response(
* response=200,
* description="Returns a HTTP status",
* @OA\Header(header="X-MINIMUM-CLIENT-VERSION", ref="#/components/headers/X-MINIMUM-CLIENT-VERSION"),
* @OA\Header(header="X-RateLimit-Remaining", ref="#/components/headers/X-RateLimit-Remaining"),
* @OA\Header(header="X-RateLimit-Limit", ref="#/components/headers/X-RateLimit-Limit"),
* ),
* @OA\Response(
* response=422,
* description="Validation error",
* @OA\JsonContent(ref="#/components/schemas/ValidationError"),
*
* ),
* @OA\Response(
* response="default",
* response="default",
* description="Unexpected Error",
* @OA\JsonContent(ref="#/components/schemas/Error"),
* ),
* )
*/
public function edocument(EDocumentRequest $request)
{
if ($request->hasFile("documents")) {
return (new ImportEDocument($request->file("documents")[0]->get(), $request->file("documents")[0]->getClientOriginalName()))->handle();
}
else {
return "No file found";
$user = auth()->user();
foreach ($request->file("documents") as $file) {
ImportEDocument::dispatch($file->get(), $file->getClientOriginalName(), $request->file("documents")->getMimeType(), $user->company());
}
return response()->json(['message' => 'Processing....'], 200);
}
}

View File

@ -59,9 +59,9 @@ class ExportController extends BaseController
/** @var \App\Models\User $user */
$user = auth()->user();
$hash = Str::uuid();
$hash = Str::uuid()->toString();
$url = \Illuminate\Support\Facades\URL::temporarySignedRoute('protected_download', now()->addHour(), ['hash' => $hash]);
Cache::put($hash, $url, now()->addHour());
Cache::put($hash, $url, 3600);
CompanyExport::dispatch($user->getCompany(), $user, $hash);

View File

@ -20,6 +20,7 @@ class GoCardlessController extends Controller
{
public function ibpRedirect(IbpRequest $request)
{
return $request
->getCompanyGateway()
->driver($request->getClient())

View File

@ -118,9 +118,36 @@ class ImportController extends Controller
})->toArray();
//Exact string match
foreach($headers as $key => $value) {
foreach($translated_keys as $tkey => $tvalue) {
$concat_needle = str_ireplace(" ", "", $tvalue['index'].$tvalue['label']);
$concat_value = str_ireplace(" ", "", $value);
if($this->testMatch($concat_value, $concat_needle)) {
$hit = $tvalue['key'];
$hints[$key] = $hit;
unset($translated_keys[$tkey]);
break;
} else {
$hints[$key] = null;
}
}
}
//Label Match
foreach($headers as $key => $value) {
if(isset($hints[$key])) {
continue;
}
foreach($translated_keys as $tkey => $tvalue) {
if($this->testMatch($value, $tvalue['label'])) {
@ -134,10 +161,9 @@ class ImportController extends Controller
}
}
//second pass using the index of the translation here
//Index matching pass using the index of the translation here
foreach($headers as $key => $value) {
if(isset($hints[$key])) {
continue;

View File

@ -0,0 +1,63 @@
<?php
/**
* Invoice Ninja (https://invoiceninja.com).
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2024. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www.elastic.co/licensing/elastic-license
*/
namespace App\Http\Controllers;
use App\Http\Requests\Quickbooks\AuthorizedQuickbooksRequest;
use App\Libraries\MultiDB;
use Illuminate\Support\Facades\Cache;
use App\Http\Requests\Quickbooks\AuthQuickbooksRequest;
use App\Services\Quickbooks\QuickbooksService;
class ImportQuickbooksController extends BaseController
{
// private array $import_entities = [
// 'client' => 'Customer',
// 'invoice' => 'Invoice',
// 'product' => 'Item',
// 'payment' => 'Payment'
// ];
public function onAuthorized(AuthorizedQuickbooksRequest $request)
{
MultiDB::findAndSetDbByCompanyKey($request->getTokenContent()['company_key']);
$company = $request->getCompany();
$qb = new QuickbooksService($company);
$realm = $request->query('realmId');
$access_token_object = $qb->sdk()->accessTokenFromCode($request->query('code'), $realm);
$qb->sdk()->saveOAuthToken($access_token_object);
return redirect(config('ninja.react_url'));
}
/**
* Determine if the user is authorized to make this request.
*
*/
public function authorizeQuickbooks(AuthQuickbooksRequest $request, string $token)
{
MultiDB::findAndSetDbByCompanyKey($request->getTokenContent()['company_key']);
$company = $request->getCompany();
$qb = new QuickbooksService($company);
$authorizationUrl = $qb->sdk()->getAuthorizationUrl();
$state = $qb->sdk()->getState();
Cache::put($state, $token, 190);
return redirect()->to($authorizationUrl);
}
}

View File

@ -475,7 +475,10 @@ class InvoiceController extends BaseController
*/
public function destroy(DestroyInvoiceRequest $request, Invoice $invoice)
{
$this->invoice_repo->delete($invoice);
if (!$invoice->is_deleted) {
$this->invoice_repo->delete($invoice);
}
return $this->itemResponse($invoice->fresh());
}
@ -503,7 +506,7 @@ class InvoiceController extends BaseController
$invoices = Invoice::withTrashed()->whereIn('id', $this->transformKeys($ids))->company()->get();
if ($invoices->count() == 0 ) {
if ($invoices->count() == 0) {
return response()->json(['message' => 'No Invoices Found']);
}

View File

@ -0,0 +1,147 @@
<?php
/**
* Invoice Ninja (https://invoiceninja.com).
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2024. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www.elastic.co/licensing/elastic-license
*/
namespace App\Http\Controllers;
use App\Models\Company;
use App\Libraries\MultiDB;
use Illuminate\Http\Request;
use App\Jobs\Mailgun\ProcessMailgunWebhook;
use App\Jobs\Mailgun\ProcessMailgunInboundWebhook;
/**
* Class MailgunController.
*/
class MailgunController extends BaseController
{
public function __construct()
{
}
/**
* Process Mailgun Webhook.
*
*
* @OA\Post(
* path="/api/v1/mailgun_webhook",
* operationId="mailgunWebhook",
* tags={"mailgun"},
* summary="Processing webhooks from Mailgun",
* description="Adds an credit to the system",
* @OA\Parameter(ref="#/components/parameters/X-API-TOKEN"),
* @OA\Parameter(ref="#/components/parameters/X-Requested-With"),
* @OA\Parameter(ref="#/components/parameters/include"),
* @OA\Response(
* response=200,
* description="Returns the saved credit object",
* @OA\Header(header="X-MINIMUM-CLIENT-VERSION", ref="#/components/headers/X-MINIMUM-CLIENT-VERSION"),
* @OA\Header(header="X-RateLimit-Remaining", ref="#/components/headers/X-RateLimit-Remaining"),
* @OA\Header(header="X-RateLimit-Limit", ref="#/components/headers/X-RateLimit-Limit"),
* @OA\JsonContent(ref="#/components/schemas/Credit"),
* ),
* @OA\Response(
* response=422,
* description="Validation error",
* @OA\JsonContent(ref="#/components/schemas/ValidationError"),
*
* ),
* @OA\Response(
* response="default",
* description="Unexpected Error",
* @OA\JsonContent(ref="#/components/schemas/Error"),
* ),
* )
*/
public function webhook(Request $request)
{
$input = $request->all();
nlog($input);
if (\abs(\time() - $request['signature']['timestamp']) > 15) {
return response()->json(['message' => 'Success'], 200);
}
if (\hash_equals(\hash_hmac('sha256', $input['signature']['timestamp'] . $input['signature']['token'], config('services.mailgun.webhook_signing_key')), $input['signature']['signature'])) {
ProcessMailgunWebhook::dispatch($request->all())->delay(rand(2, 10));
}
return response()->json(['message' => 'Success.'], 200);
}
/**
* Process Mailgun Inbound Webhook.
*
* IMPORTANT NOTICE: mailgun does NOT strip old sended emails, therefore all past attachements are present
*
* IMPORTANT NOTICE: mailgun saves the message and attachemnts for later retrieval, therefore we can process it within a async job for performance reasons
*
*
* @OA\Post(
* path="/api/v1/mailgun_inbound_webhook",
* operationId="mailgunInboundWebhook",
* tags={"mailgun"},
* summary="Processing inbound webhooks from Mailgun",
* description="Adds an credit to the system",
* @OA\Parameter(ref="#/components/parameters/X-API-TOKEN"),
* @OA\Parameter(ref="#/components/parameters/X-Requested-With"),
* @OA\Parameter(ref="#/components/parameters/include"),
* @OA\Response(
* response=200,
* description="Returns the saved credit object",
* @OA\Header(header="X-MINIMUM-CLIENT-VERSION", ref="#/components/headers/X-MINIMUM-CLIENT-VERSION"),
* @OA\Header(header="X-RateLimit-Remaining", ref="#/components/headers/X-RateLimit-Remaining"),
* @OA\Header(header="X-RateLimit-Limit", ref="#/components/headers/X-RateLimit-Limit"),
* @OA\JsonContent(ref="#/components/schemas/Credit"),
* ),
* @OA\Response(
* response=422,
* description="Validation error",
* @OA\JsonContent(ref="#/components/schemas/ValidationError"),
*
* ),
* @OA\Response(
* response="default",
* description="Unexpected Error",
* @OA\JsonContent(ref="#/components/schemas/Error"),
* ),
* )
*/
public function inboundWebhook(Request $request)
{
$input = $request->all();
nlog($input);
if (!array_key_exists('sender', $input) || !array_key_exists('recipient', $input) || !array_key_exists('message-url', $input)) {
nlog('Failed: Message could not be parsed, because required parameters are missing. Please ensure contacting this api-endpoint with a store & notify operation instead of a forward operation!');
return response()->json(['message' => 'Failed. Missing Parameters. Use store and notify!'], 400);
}
// @turbo124 TODO: how to check for services.mailgun.webhook_signing_key on company level, when custom credentials are defined
// TODO: validation for client mail credentials by recipient
$authorizedByHash = \hash_equals(\hash_hmac('sha256', $input['timestamp'] . $input['token'], config('services.mailgun.webhook_signing_key')), $input['signature']);
$authorizedByToken = $request->has('token') && $request->get('token') == config('ninja.inbound_mailbox.inbound_webhook_token');
if (!$authorizedByHash && !$authorizedByToken)
return response()->json(['message' => 'Unauthorized'], 403);
/** @var \App\Models\Company $company */
$company = MultiDB::findAndSetDbByExpenseMailbox($input["recipient"]);
if(!$company)
return response()->json(['message' => 'Ok'], 200); // Fail gracefully
ProcessMailgunInboundWebhook::dispatch($input["sender"], $input["recipient"], $input["message-url"], $company)->delay(rand(2, 10));
return response()->json(['message' => 'Success.'], 200);
}
}

View File

@ -1,43 +0,0 @@
<?php
/**
* Invoice Ninja (https://invoiceninja.com).
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2024. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www.elastic.co/licensing/elastic-license
*/
namespace App\Http\Controllers;
use App\Jobs\Mailgun\ProcessMailgunWebhook;
use App\Jobs\PostMark\ProcessPostmarkWebhook;
use Illuminate\Http\Request;
/**
* Class MailgunWebhookController.
*/
class MailgunWebhookController extends BaseController
{
public function __construct()
{
}
public function webhook(Request $request)
{
$input = $request->all();
if (\abs(\time() - $request['signature']['timestamp']) > 15) {
return response()->json(['message' => 'Success'], 200);
}
if(\hash_equals(\hash_hmac('sha256', $input['signature']['timestamp'] . $input['signature']['token'], config('services.mailgun.webhook_signing_key')), $input['signature']['signature'])) {
ProcessMailgunWebhook::dispatch($request->all())->delay(rand(2,10));
}
return response()->json(['message' => 'Success.'], 200);
}
}

View File

@ -22,7 +22,6 @@ use Illuminate\Support\Str;
class OneTimeTokenController extends BaseController
{
public function __construct()
{
parent::__construct();
@ -74,6 +73,10 @@ class OneTimeTokenController extends BaseController
'is_react' => $request->hasHeader('X-REACT') ? true : false,
];
if($request->institution_id) {
$data['institution_id'] = $request->institution_id;
}
Cache::put($hash, $data, 3600);
return response()->json(['hash' => $hash], 200);

View File

@ -25,7 +25,7 @@ class PaymentNotificationWebhookController extends Controller
{
/** @var \App\Models\CompanyGateway $company_gateway */
$company_gateway = CompanyGateway::find($this->decodePrimaryKey($company_gateway_id));
/** @var \App\Models\Client $client */
$client = Client::find($this->decodePrimaryKey($client_hash));

View File

@ -12,6 +12,11 @@
namespace App\Http\Controllers;
use App\Jobs\PostMark\ProcessPostmarkWebhook;
use App\Libraries\MultiDB;
use App\Services\InboundMail\InboundMail;
use App\Services\InboundMail\InboundMailEngine;
use App\Utils\TempFile;
use Illuminate\Support\Carbon;
use Illuminate\Http\Request;
/**
@ -19,7 +24,6 @@ use Illuminate\Http\Request;
*/
class PostMarkController extends BaseController
{
public function __construct()
{
}
@ -61,11 +65,271 @@ class PostMarkController extends BaseController
public function webhook(Request $request)
{
if ($request->header('X-API-SECURITY') && $request->header('X-API-SECURITY') == config('services.postmark.token')) {
ProcessPostmarkWebhook::dispatch($request->all())->delay(10);
ProcessPostmarkWebhook::dispatch($request->all())->delay(rand(2, 10));
return response()->json(['message' => 'Success'], 200);
}
return response()->json(['message' => 'Unauthorized'], 403);
}
/**
* Process Postmark Webhook.
*
* IMPORTANT NOTICE: postmark does NOT strip old sended emails, therefore also all past attachements are present
*
* IMPORTANT NOTICE: postmark does not saves attachements for later retrieval, therefore we cannot process it within a async job
*
* @OA\Post(
* path="/api/v1/postmark_inbound_webhook",
* operationId="postmarkInboundWebhook",
* tags={"postmark"},
* summary="Processing inbound webhooks from PostMark",
* description="Adds an credit to the system",
* @OA\Parameter(ref="#/components/parameters/X-API-TOKEN"),
* @OA\Parameter(ref="#/components/parameters/X-Requested-With"),
* @OA\Parameter(ref="#/components/parameters/include"),
* @OA\Response(
* response=200,
* description="Returns the saved credit object",
* @OA\Header(header="X-MINIMUM-CLIENT-VERSION", ref="#/components/headers/X-MINIMUM-CLIENT-VERSION"),
* @OA\Header(header="X-RateLimit-Remaining", ref="#/components/headers/X-RateLimit-Remaining"),
* @OA\Header(header="X-RateLimit-Limit", ref="#/components/headers/X-RateLimit-Limit"),
* @OA\JsonContent(ref="#/components/schemas/Credit"),
* ),
* @OA\Response(
* response=422,
* description="Validation error",
* @OA\JsonContent(ref="#/components/schemas/ValidationError"),
*
* ),
* @OA\Response(
* response="default",
* description="Unexpected Error",
* @OA\JsonContent(ref="#/components/schemas/Error"),
* ),
* )
*
* array (
* 'FromName' => 'Max Mustermann',
* 'MessageStream' => 'inbound',
* 'From' => 'max@mustermann.de',
* 'FromFull' =>
* array (
* 'Email' => 'max@mustermann.de',
* 'Name' => 'Max Mustermann',
* 'MailboxHash' => NULL,
* ),
* 'To' => '370c69ad9e41d616fc914b3c60250224@inbound.postmarkapp.com',
* 'ToFull' =>
* array (
* 0 =>
* array (
* 'Email' => '370c69ad9e41d616fc914b3c60250224@inbound.postmarkapp.com',
* 'Name' => NULL,
* 'MailboxHash' => NULL,
* ),
* ),
* 'Cc' => NULL,
* 'CcFull' =>
* array (
* ),
* 'Bcc' => NULL,
* 'BccFull' =>
* array (
* ),
* 'OriginalRecipient' => '370c69ad9e41d616fc914b3c60250224@inbound.postmarkapp.com',
* 'Subject' => 'Re: adaw',
* 'MessageID' => 'd37fde00-b4cf-4b64-ac64-e9f6da523c25',
* 'ReplyTo' => NULL,
* 'MailboxHash' => NULL,
* 'Date' => 'Sun, 24 Mar 2024 13:17:52 +0100',
* 'TextBody' => 'wadwad
*
* Am So., 24. März 2024 um 13:17 Uhr schrieb Max Mustermann <max@mustermann.de>:
*
* > test
* >
*
* --
* test.de - Max Mustermann <https://test.de/>kontakt@test.de
* <mailto:kontakt@test.de>',
* 'HtmlBody' => '<div dir="ltr">wadwad</div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">Am So., 24. März 2024 um 13:17 Uhr schrieb Max Mustermann &lt;<a href="mailto:max@mustermann.de">max@mustermann.de</a>&gt;:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr">test</div>
* </blockquote></div>
*
* <br>
* <font size="3"><a href="https://test.de/" target="_blank">test.de - Max Mustermann</a></font><div><a href="mailto:kontakt@test.de" style="font-size:medium" target="_blank">kontakt@test.de</a><br></div>',
* 'StrippedTextReply' => 'wadwad
*
* Am So., 24. März 2024 um 13:17 Uhr schrieb Max Mustermann <max@mustermann.de>:',
* 'Tag' => NULL,
* 'Headers' =>
* array (
* 0 =>
* array (
* 'Name' => 'Return-Path',
* 'Value' => '<max@mustermann.de>',
* ),
* 1 =>
* array (
* 'Name' => 'Received',
* 'Value' => 'by p-pm-inboundg02a-aws-euwest1a.inbound.postmarkapp.com (Postfix, from userid 996) id 8ED1A453CA4; Sun, 24 Mar 2024 12:18:10 +0000 (UTC)',
* ),
* 2 =>
* array (
* 'Name' => 'X-Spam-Checker-Version',
* 'Value' => 'SpamAssassin 3.4.0 (2014-02-07) on p-pm-inboundg02a-aws-euwest1a',
* ),
* 3 =>
* array (
* 'Name' => 'X-Spam-Status',
* 'Value' => 'No',
* ),
* 4 =>
* array (
* 'Name' => 'X-Spam-Score',
* 'Value' => '-0.1',
* ),
* 5 =>
* array (
* 'Name' => 'X-Spam-Tests',
* 'Value' => 'DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,HTML_MESSAGE, RCVD_IN_DNSWL_NONE,RCVD_IN_MSPIKE_H2,RCVD_IN_ZEN_BLOCKED_OPENDNS, SPF_HELO_NONE,SPF_PASS,URIBL_DBL_BLOCKED_OPENDNS,URIBL_ZEN_BLOCKED_OPENDNS',
* ),
* 6 =>
* array (
* 'Name' => 'Received-SPF',
* 'Value' => 'pass (test.de: Sender is authorized to use \'max@mustermann.de\' in \'mfrom\' identity (mechanism \'include:_spf.google.com\' matched)) receiver=p-pm-inboundg02a-aws-euwest1a; identity=mailfrom; envelope-from="max@mustermann.de"; helo=mail-lf1-f51.google.com; client-ip=209.85.167.51',
* ),
* 7 =>
* array (
* 'Name' => 'Received',
* 'Value' => 'from mail-lf1-f51.google.com (mail-lf1-f51.google.com [209.85.167.51]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by p-pm-inboundg02a-aws-euwest1a.inbound.postmarkapp.com (Postfix) with ESMTPS id 437BD453CA2 for <370c69ad9e41d616fc914b3c60250224@inbound.postmarkapp.com>; Sun, 24 Mar 2024 12:18:10 +0000 (UTC)',
* ),
* 8 =>
* array (
* 'Name' => 'Received',
* 'Value' => 'by mail-lf1-f51.google.com with SMTP id 2adb3069b0e04-513cf9bacf1so4773866e87.0 for <370c69ad9e41d616fc914b3c60250224@inbound.postmarkapp.com>; Sun, 24 Mar 2024 05:18:10 -0700 (PDT)',
* ),
* 9 =>
* array (
* 'Name' => 'DKIM-Signature',
* 'Value' => 'v=1; a=rsa-sha256; c=relaxed/relaxed; d=test.de; s=google; t=1711282689; x=1711887489; darn=inbound.postmarkapp.com; h=to:subject:message-id:date:from:in-reply-to:references:mime-version :from:to:cc:subject:date:message-id:reply-to; bh=NvjmqLXF/5L5ZrpToR/6FgVOhTOGC9j0/B2Na5Ke6J8=; b=AMXIEoh6yGrOT6X3eBBClQ3NXFNuEoqxeM6aPONsqbpShAcT24iAJmqXylaLHv3fyX Hm6mwp3a029NnrLP/VRyKZbzIMBN2iycidtrEMXF/Eg2e42Q/08/2dZ7nxH6NqE/jz01 3M7qvwHvuoZ2Knhj7rnZc6I5m/nFxBsZc++Aj0Vv9sFoWZZooqAeTXbux1I5NyE17MrL D6byca43iINARZN7XOkoChRRZoZbOqZEtc2Va5yw7v+aYguLB4HHrIFC7G+L8hAJ0IAo 3R3DFeBw58M1xtxXCREI8Y6qMQTw60XyFw0gVmZzqR4hZiTerBSJJsZLZOBgmXxq3WLS +xVQ==',
* ),
* 10 =>
* array (
* 'Name' => 'X-Google-DKIM-Signature',
* 'Value' => 'v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1711282689; x=1711887489; h=to:subject:message-id:date:from:in-reply-to:references:mime-version :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=NvjmqLXF/5L5ZrpToR/6FgVOhTOGC9j0/B2Na5Ke6J8=; b=uKoMhir+MX/wycNEr29Sffj45ooKksCJ1OfSRkIIGHk0rnHn8Vh+c7beYipwRPW4F2 h46K64vtIX00guYMdL2Qo2eY96+wALTqHCy67PGhvotVTROz21yxjx62pCDPGs5tefOu IkyxoybpIK8zAfLoDTd9p2GIrr5brKJyB2w1NQc1htxTQ5D4RgBxUAOKv4uVEr8r47iA MIo5d8/AifA+vCOAh7iJ7EmvDQ1R+guhQyH9m1Jo8PLapiYuHXggpBJvooyGuflKqbnt gJ/dscEr4d5aWJbw/x1dmIJ5gyJPGdBWq8NRqV/qbkXQW3H/gylifDUPXbki+EQBD5Yu EuLQ==',
* ),
* 11 =>
* array (
* 'Name' => 'X-Gm-Message-State',
* 'Value' => 'AOJu0Yxpbp1sRh17lNzg+pLnIx1jCn8ZFJQMgFuHK+6Z8RqFS5KKKTxR 8onpEbxWYYVUbrJFExNBHPD/3jdxqifCVVNaDmbpwHgmW5lHLJmA5vYRq5NFZ9OA6zKx/N6Gipr iXE4fXmSqghFNTzy9V/RT08Zp+F5RiFh/Ta6ltQl8XfCPFfSawLz6cagUgt8bBuF4RqdrYmWwzj ty86V5Br1htRNEFYivoXnNmaRcsD0tca1D23ny62O6RwWugrj1IpAYhViNyTZAWu+loKgfjJJoI MsyiSU=',
* ),
* 12 =>
* array (
* 'Name' => 'X-Google-Smtp-Source',
* 'Value' => 'AGHT+IEdtZqbVI6j7WLeaSL3dABGSnWIXaSjbYqXvFvE2H+f2zsn0gknQ4OdTJecQRCabpypVF2ue91Jb7aKl6RiyEQ=',
* ),
* 13 =>
* array (
* 'Name' => 'X-Received',
* 'Value' => 'by 2002:a19:385a:0:b0:513:c876:c80a with SMTP id d26-20020a19385a000000b00513c876c80amr2586776lfj.34.1711282689140; Sun, 24 Mar 2024 05:18:09 -0700 (PDT)',
* ),
* 14 =>
* array (
* 'Name' => 'MIME-Version',
* 'Value' => '1.0',
* ),
* 15 =>
* array (
* 'Name' => 'References',
* 'Value' => '<CADfEuNsNFmNNCJDPjpS36amoLv2XEm41HmgYJT7Tj=R96PkxnA@mail.gmail.com>',
* ),
* 16 =>
* array (
* 'Name' => 'In-Reply-To',
* 'Value' => '<CADfEuNsNFmNNCJDPjpS36amoLv2XEm41HmgYJT7Tj=R96PkxnA@mail.gmail.com>',
* ),
* 17 =>
* array (
* 'Name' => 'Message-ID',
* 'Value' => '<CADfEuNvyCLsnp=CwJ3BF=-L6rn=o+DmUOPP6Cp4F-SO0p0hVwQ@mail.gmail.com>',
* ),
* ),
* 'Attachments' =>
* array (
* array (
* 'Content' => "base64-String",
* 'ContentLength' => 60164,
* 'Name' => 'Unbenannt.png',
* 'ContentType' => 'image/png',
* 'ContentID' => 'ii_luh2h8lg0',
* )
* ),
* )
*/
public function inboundWebhook(Request $request)
{
$input = $request->all();
if (!$request->has('token') || $request->token != config('ninja.inbound_mailbox.inbound_webhook_token'))
return response()->json(['message' => 'Unauthorized'], 403);
if (!(array_key_exists("MessageStream", $input) && $input["MessageStream"] == "inbound") || !array_key_exists("To", $input) || !array_key_exists("From", $input) || !array_key_exists("MessageID", $input)) {
nlog('Failed: Message could not be parsed, because required parameters are missing.');
return response()->json(['message' => 'Failed. Missing/Invalid Parameters.'], 400);
}
$company = MultiDB::findAndSetDbByExpenseMailbox($input["ToFull"][0]["Email"]);
if (!$company) {
nlog('[PostmarkInboundWebhook] unknown Expense Mailbox occured while handling an inbound email from postmark: ' . $input["To"]);
return response()->json(['message' => 'Ok'], 200);
}
$inboundEngine = new InboundMailEngine($company);
if ($inboundEngine->isInvalidOrBlocked($input["From"], $input["ToFull"][0]["Email"])) {
return response()->json(['message' => 'Blocked.'], 403);
}
try { // important to save meta if something fails here to prevent spam
// prepare data for ingresEngine
$inboundMail = new InboundMail();
$inboundMail->from = $input["From"] ?? '';
$inboundMail->to = $input["To"]; // usage of data-input, because we need a single email here
$inboundMail->subject = $input["Subject"] ?? '';
$inboundMail->body = $input["HtmlBody"] ?? '';
$inboundMail->text_body = $input["TextBody"] ?? '';
$inboundMail->date = Carbon::createFromTimeString($input["Date"]);
// parse documents as UploadedFile from webhook-data
foreach ($input["Attachments"] as $attachment) {
$inboundMail->documents[] = TempFile::UploadedFileFromBase64($attachment["Content"], $attachment["Name"], $attachment["ContentType"]);
}
} catch (\Exception $e) {
$inboundEngine->saveMeta($input["From"], $input["To"]); // important to save this, to protect from spam
throw $e;
}
// perform
try {
$inboundEngine->handleExpenseMailbox($inboundMail);
} catch (\Exception $e) {
if ($e->getCode() == 409)
return response()->json(['message' => $e->getMessage()], 409);
throw $e;
}
return response()->json(['message' => 'Success'], 200);
}
}

View File

@ -148,6 +148,9 @@ class PreviewController extends BaseController
! empty(request()->input('entity')) &&
! empty(request()->input('entity_id'))) {
if($request->input('entity') == 'purchase_order')
return $preview = app(\App\Http\Controllers\PreviewPurchaseOrderController::class)->show($request);
$design_object = json_decode(json_encode(request()->input('design')));
if (! is_object($design_object)) {
@ -293,10 +296,14 @@ class PreviewController extends BaseController
$ts = (new TemplateService());
try {
$ts->setCompany($company)
->setTemplate($design_object)
->mock();
} catch(SyntaxError $e) {
} catch(\Exception $e) {
return response()->json(['message' => 'invalid data access', 'errors' => ['design.design.body' => $e->getMessage()]], 422);
}
if (request()->query('html') == 'true') {

View File

@ -36,6 +36,7 @@ use App\Utils\Traits\Pdf\PageNumbering;
use App\Utils\VendorHtmlEngine;
use Illuminate\Support\Facades\App;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Request;
use Illuminate\Support\Facades\Response;
use Turbo124\Beacon\Facades\LightLogs;
@ -83,7 +84,7 @@ class PreviewPurchaseOrderController extends BaseController
* ),
* )
*/
public function show()
public function show($request)
{
if (request()->has('entity') &&
request()->has('entity_id') &&

Some files were not shown because too many files have changed in this diff Show More