diff --git a/app/Domains/Housing/Http/Controllers/ProjectController.php b/app/Domains/Housing/Http/Controllers/ProjectController.php index d5d29df8..a9f2a1f8 100644 --- a/app/Domains/Housing/Http/Controllers/ProjectController.php +++ b/app/Domains/Housing/Http/Controllers/ProjectController.php @@ -2,15 +2,15 @@ namespace App\Domains\Housing\Http\Controllers; -use App\Domains\Housing\Models\Occurrence; use App\Http\Controllers\Controller; +use App\Domains\Housing\Models\Occurrence; class ProjectController extends Controller { public function __invoke() { return inertia('Housing/Index', [ - 'checks' => Occurrence::where('team_id', auth()->user()->current_team_id)->limit(4)->get(), + 'checks' => Occurrence::where('team_id', auth()->user()->current_team_id)->limit(6)->get(), ]); } } diff --git a/app/Domains/Integration/Actions/BHD.php b/app/Domains/Integration/Actions/BHD.php index 6f2af98f..6a009f39 100644 --- a/app/Domains/Integration/Actions/BHD.php +++ b/app/Domains/Integration/Actions/BHD.php @@ -49,12 +49,7 @@ public function getDescription(): string return 'Parse an email alert or notification from BHD Leon Bank'; } - /** - * Validate and create a new team for the given user. - * - * @param Google_Calendar_Events $calendarEvents - * @return void - */ + public static function parseAlert( Automation $automation, mixed $payload, @@ -62,16 +57,11 @@ public static function parseAlert( AutomationTaskAction $previousTask, AutomationTaskAction $trigger ) { - + echo "\n Parsing alert \n\n"; return (new BHDAlert())->handle($automation, $payload); } - /** - * Validate and create a new team for the given user. - * - * @param Google_Calendar_Events $calendarEvents - * @return void - */ + public static function parseNotification( Automation $automation, mixed $payload, @@ -79,7 +69,7 @@ public static function parseNotification( AutomationTaskAction $previousTask, AutomationTaskAction $trigger ) { - + echo "\n Parsing notification"; return (new BHDNotification())->handle($automation, $payload); } @@ -87,12 +77,12 @@ public static function getMessageType($mail) { try { $body = new Crawler($mail['message']); - $tdValues = $body->filter('[class*=table_trans_body] td')->each(function (Crawler $node) { + $tdValues = $body->filter('[class*=alert_div] td')->each(function (Crawler $node) { return $node->text(); }); return empty($tdValues) ? 'notification' : 'alert'; - } catch (Exception) { + } catch (Exception $e) { return 'notification'; } } diff --git a/app/Domains/Integration/Actions/BHDAlert.php b/app/Domains/Integration/Actions/BHDAlert.php index 2f55e2fe..e9a810d1 100644 --- a/app/Domains/Integration/Actions/BHDAlert.php +++ b/app/Domains/Integration/Actions/BHDAlert.php @@ -2,8 +2,10 @@ namespace App\Domains\Integration\Actions; +use Exception; use Symfony\Component\DomCrawler\Crawler; use App\Domains\Automation\Models\Automation; +use App\Domains\Transaction\Services\YNABService; use App\Domains\Integration\Concerns\MailToTransaction; use App\Domains\Integration\Concerns\TransactionDataDTO; @@ -13,25 +15,28 @@ class BHDAlert implements MailToTransaction public function handle(Automation $automation, mixed $mail, int $index = 0): TransactionDataDTO { + try { + $body = new Crawler($mail['message']); + $product = $body->filter('[class*=titleA] + p')->first()->text(); + $tdValues = $body->filter('[class*=table_trans] tbody td')->each(function (Crawler $node) { + return $node->text(); + }); - $body = new Crawler($mail['message']); - $product = $body->filter('[class*=titleA] + p')->first()->text(); - $tdValues = $body->filter('[class*=table_trans_body] td')->each(function (Crawler $node) { - return $node->text(); - }); + $total = YNABService::extractMoneyCurrency($tdValues[2]); + $type = BHD::parseTypes(strtolower($tdValues[5])) ?? 1; - $total = (int) str_replace(',', '', $tdValues[2]); - $type = BHD::parseTypes(strtolower($tdValues[5])) ?? 1; - - return new TransactionDataDTO([ - 'id' => (int) $mail['id'], - 'date' => date('Y-m-d', strtotime($mail['date'])), - 'payee' => $tdValues[3], - 'category' => '', - 'categoryGroup' => '', - 'description' => $product, - 'amount' => $total * $type, - 'currencyCode' => BHD::parseCurrency($tdValues[1]), - ]); + return new TransactionDataDTO([ + 'id' => (int) $mail['id'], + 'date' => date('Y-m-d', strtotime($mail['date'])), + 'payee' => $tdValues[3], + 'category' => '', + 'categoryGroup' => '', + 'description' => $product, + 'amount' => $total->amount * $type, + 'currencyCode' => BHD::parseCurrency($tdValues[1]), + ]); + } catch (Exception $e) { + throw $e; + } } } diff --git a/app/Domains/Integration/Actions/BHDNotification.php b/app/Domains/Integration/Actions/BHDNotification.php index 08e04d80..a2dedbe3 100644 --- a/app/Domains/Integration/Actions/BHDNotification.php +++ b/app/Domains/Integration/Actions/BHDNotification.php @@ -54,26 +54,28 @@ public function handle(Automation $automation, mixed $mail, int $index = 0): Tra 'name' => 'type', ], ]; - try { - foreach ($tableIds as $fieldName => $field) { - $bhdOutput[$field['name']] = $this->{$field['processor']}($body->filter("[id*=${fieldName}]")->first()->text()); + foreach ($tableIds as $fieldName => $field) { + try { + $bhdOutput[$field['name']] = $this->{$field['processor']}($body->filter("[id*=$fieldName]")->first()->text()); + } catch (Exception $e) { + echo $e->getMessage() . "\n\n"; + Log::error($e->getMessage(), [$e]); + continue; } - - return new TransactionDataDTO([ - 'id' => (int) $mail['id'], - 'date' => $bhdOutput['date'], - 'payee' => $bhdOutput['seller'], - 'category' => '', - 'categoryGroup' => '', - 'description' => $bhdOutput['product'].':'.$bhdOutput['description'], - 'amount' => $bhdOutput['amount']->amount * 1, - 'currencyCode' => $bhdOutput['amount']->currencyCode, - ]); - } catch (Exception $e) { - echo $e->getMessage(); - Log::error($e->getMessage(), [$e]); - return null; } + + print_r([$bhdOutput['amount']]); + + return new TransactionDataDTO([ + 'id' => (int) $mail['id'], + 'date' => $bhdOutput['date'], + 'payee' => $bhdOutput['seller'], + 'category' => '', + 'categoryGroup' => '', + 'description' => $bhdOutput['product'].':'.$bhdOutput['description'], + 'amount' => $bhdOutput['amount']->amount * 1, + 'currencyCode' => $bhdOutput['amount']->currencyCode, + ]); } public function processResult($value) diff --git a/app/Domains/Integration/Actions/GmailReceived.php b/app/Domains/Integration/Actions/GmailReceived.php index 1cb004da..60d3fec4 100644 --- a/app/Domains/Integration/Actions/GmailReceived.php +++ b/app/Domains/Integration/Actions/GmailReceived.php @@ -80,6 +80,7 @@ public static function handle(Automation $automation, $lastData = null, $task = if ($taskIndex !== 0) { $actionEntity = $task->entity; try { + echo "\n starting workflow-task:$task->id:$task->name"; $payload = $actionEntity::handle($automation, $payload, $task, $previousTask, $tasks[0]); $previousTask = $task; } catch (\Exception $e) { diff --git a/app/Domains/Integration/Actions/TransactionCreateEntry.php b/app/Domains/Integration/Actions/TransactionCreateEntry.php index f36f536a..8c41fb5a 100644 --- a/app/Domains/Integration/Actions/TransactionCreateEntry.php +++ b/app/Domains/Integration/Actions/TransactionCreateEntry.php @@ -67,10 +67,11 @@ public static function handle( $transactionService = new TransactionService(); if ($transaction = $transactionService->findIfDuplicated($transactionData)) { - print_r($transaction); return $transaction; } + print_r([$transaction, "new transaction"]); + $transaction = Transaction::createTransaction($transactionData); User::find($automation->user_id)->notify(new EntryGenerated($transaction)); diff --git a/app/Domains/Transaction/Models/BillingCycle.php b/app/Domains/Transaction/Models/BillingCycle.php index 10e80547..8d4ac820 100644 --- a/app/Domains/Transaction/Models/BillingCycle.php +++ b/app/Domains/Transaction/Models/BillingCycle.php @@ -144,7 +144,8 @@ public static function checkPayments($payable) } public function linkPayment(Transaction $transaction, $formData) { - if ($this->debt <= 0) { + $paid = $this->payments; + if ($paid >= $this->total) { throw new Exception("The document {$this->concept} is already paid"); } diff --git a/app/Domains/Transaction/Services/ReportService.php b/app/Domains/Transaction/Services/ReportService.php index 044d7253..2ee1738c 100644 --- a/app/Domains/Transaction/Services/ReportService.php +++ b/app/Domains/Transaction/Services/ReportService.php @@ -90,7 +90,7 @@ public static function getIncomeVsExpenses($teamId, $timeUnitDiff = 2, $startDat - $income = self::getIncomeByPayeeInPeriod($teamId, $startDate, $endDate); + $income = self::getTransactionsByPayeeInPeriod($teamId, $startDate, $endDate); $incomeCategories = $income->groupBy($timeUnit); $dates = $expensesGroup->keys(); @@ -155,7 +155,7 @@ public static function getExpensesByYear($year, $teamId) ->get(); } - public static function getIncomeByPayeeInPeriod($teamId, $startDate, $endDate) + public static function getTransactionsByPayeeInPeriod($teamId, $startDate, $endDate) { return TransactionLine::byTeam($teamId) ->balance() diff --git a/app/Domains/Transaction/Services/TransactionService.php b/app/Domains/Transaction/Services/TransactionService.php index 5c099479..5b4c5f1d 100644 --- a/app/Domains/Transaction/Services/TransactionService.php +++ b/app/Domains/Transaction/Services/TransactionService.php @@ -312,7 +312,7 @@ public static function getIncomeVsExpenses($teamId, $timeUnitDiff = 2, $timeUnit return ["{$item->group_name}:{$item->name}" => $item]; }); - $income = self::getIncomeByPayeeInPeriod($teamId, $startDate, $endDate); + $income = self::getTransactionsByPayeeInPeriod($teamId, $startDate, $endDate); $incomeCategories = $income->unique('id')->sortBy('index_field')->values(); $incomeCategoriesGroup = $income->sortBy('index_field')->mapToGroups(function ($item) { return [$item->name => $item]; @@ -418,7 +418,7 @@ public static function getForExport($teamId) ->toArray(); } - public static function getIncomeByPayeeInPeriod($teamId, $startDate, $endDate, $direction = Transaction::DIRECTION_DEBIT) + public static function getTransactionsByPayeeInPeriod($teamId, $startDate, $endDate, $direction = Transaction::DIRECTION_DEBIT) { return DB::table('payees') ->selectRaw('sum(COALESCE(total,0)) as total, date_format(transactions.date, "%Y-%m-01") as date, payees.name, payees.id') diff --git a/app/Http/Controllers/Finance/FinanceTrendController.php b/app/Http/Controllers/Finance/FinanceTrendController.php index ca9012c5..c5572f04 100644 --- a/app/Http/Controllers/Finance/FinanceTrendController.php +++ b/app/Http/Controllers/Finance/FinanceTrendController.php @@ -129,10 +129,10 @@ public function payee(Request $request) $teamId = $request->user()->current_team_id; - $data = TransactionService::getIncomeByPayeeInPeriod($teamId, $startDate, $endDate, $direction); + $data = TransactionService::getTransactionsByPayeeInPeriod($teamId, $startDate, $endDate, $direction); return [ - 'data' => $data, + 'data' => $data->sortByDesc('total')->values(), 'metaData' => [ 'title' => 'Payee Trends', 'name' => 'payee' diff --git a/components.d.ts b/components.d.ts index f5745997..285f8b56 100644 --- a/components.d.ts +++ b/components.d.ts @@ -7,18 +7,29 @@ export {} /* prettier-ignore */ declare module 'vue' { export interface GlobalComponents { + IFluentFoodApple20Filled: typeof import('~icons/fluent/food-apple20-filled')['default'] + IIonEllipsisVertical: typeof import('~icons/ion/ellipsis-vertical')['default'] + IMaterialSymbolsBrightnessAlertOutlineRounded: typeof import('~icons/material-symbols/brightness-alert-outline-rounded')['default'] IMdiBankTransfer: typeof import('~icons/mdi/bank-transfer')['default'] IMdiBankTransferIn: typeof import('~icons/mdi/bank-transfer-in')['default'] IMdiBankTransferOut: typeof import('~icons/mdi/bank-transfer-out')['default'] IMdiBell: typeof import('~icons/mdi/bell')['default'] IMdiCallSplit: typeof import('~icons/mdi/call-split')['default'] IMdiCheck: typeof import('~icons/mdi/check')['default'] + IMdiChevronDown: typeof import('~icons/mdi/chevron-down')['default'] IMdiChevronLeft: typeof import('~icons/mdi/chevron-left')['default'] IMdiChevronRight: typeof import('~icons/mdi/chevron-right')['default'] + IMdiChevronUp: typeof import('~icons/mdi/chevron-up')['default'] IMdiClose: typeof import('~icons/mdi/close')['default'] IMdiEllipsisVertical: typeof import('~icons/mdi/ellipsis-vertical')['default'] IMdiEmailCheck: typeof import('~icons/mdi/email-check')['default'] + IMdiExport: typeof import('~icons/mdi/export')['default'] IMdiFile: typeof import('~icons/mdi/file')['default'] + IMdiFilter: typeof import('~icons/mdi/filter')['default'] + IMdiHistory: typeof import('~icons/mdi/history')['default'] + IMdiLink: typeof import('~icons/mdi/link')['default'] + IMdiLock: typeof import('~icons/mdi/lock')['default'] + IMdiMinus: typeof import('~icons/mdi/minus')['default'] IMdiMoney: typeof import('~icons/mdi/money')['default'] IMdiStar: typeof import('~icons/mdi/star')['default'] IMdiStarOutline: typeof import('~icons/mdi/star-outline')['default'] diff --git a/package.json b/package.json index 0025fabd..1636835d 100644 --- a/package.json +++ b/package.json @@ -38,13 +38,13 @@ "@iconify-json/fluent": "^1.1.59", "@iconify-json/ic": "^1.1.17", "@iconify-json/ion": "^1.1.18", - "@iconify-json/material-symbols": "^1.1.82", + "@iconify-json/material-symbols": "^1.1.85", "@iconify-json/mdi": "^1.1.67", "@inertiajs/vue3": "^1.2.0", "@mertasan/tailwindcss-variables": "^2.7.0", "@tailwindcss/typography": "^0.5.13", - "@vitejs/plugin-vue": "^5.0.5", - "@vue/server-renderer": "^3.4.27", + "@vitejs/plugin-vue": "^5.1.1", + "@vue/server-renderer": "^3.4.34", "@vueuse/core": "^10.11.0", "atmosphere-ui": "^1.3.5", "autoprefixer": "^10.4.19", @@ -55,24 +55,24 @@ "eslint-config-prettier": "^9.1.0", "eslint-plugin-html": "^8.1.1", "eslint-plugin-prettier": "^5.2.1", - "eslint-plugin-vue": "^9.26.0", + "eslint-plugin-vue": "^9.27.0", "exact-math": "^2.2.3", - "firebase": "^10.8.0", + "firebase": "^10.12.4", "laravel-vite-plugin": "^1.0.5", "lodash": "^4.17.21", "naive-ui": "^2.39.0", - "postcss": "^8.4.39", + "postcss": "^8.4.40", "prettier": "^3.3.3", "sass": "^1.77.8", "slug": "^9.1.0", - "tailwindcss": "^3.4.4", - "typescript": "^5.4.5", - "unplugin-icons": "^0.18.5", + "tailwindcss": "^3.4.7", + "typescript": "^5.5.4", + "unplugin-icons": "^0.19.0", "unplugin-vue-components": "^0.27.3", "uuid": "^10.0.0", - "vite": "^5.3.4", - "vite-plugin-pwa": "^0.20.0", - "vitepress": "^1.2.3", + "vite": "^5.3.5", + "vite-plugin-pwa": "^0.20.1", + "vitepress": "^1.3.1", "vue": "^3.4.33", "vue-multiselect": "^3.0.0", "vue3-apexcharts": "^1.5.3", @@ -83,11 +83,11 @@ "@originjs/vite-plugin-federation": "^1.3.5", "@vueuse/components": "^10.11.0", "chart.js": "^4.4.3", - "element-plus": "^2.7.7", + "element-plus": "^2.7.8", "floating-vue": "^5.2.2", "fuse.js": "^7.0.0", "luxon": "^3.4.4", - "pinia": "^2.1.7", + "pinia": "^2.2.0", "randomcolor": "^0.6.2", "vanilla-icon-picker": "^1.3.0", "vue-chartjs": "^5.3.1", diff --git a/resources/js/Components/widgets/ChoreWidget.vue b/resources/js/Components/widgets/ChoreWidget.vue index 2966d8fd..e51145ff 100644 --- a/resources/js/Components/widgets/ChoreWidget.vue +++ b/resources/js/Components/widgets/ChoreWidget.vue @@ -10,7 +10,7 @@ defineProps<{