|
11105
|
+SlackEDHomeDMSActivityFilesLater..•More+FileEditV +SlackEDHomeDMSActivityFilesLater..•More+FileEditViewGoHistoryWindowHelpJiminny ...# Starredplatform-inner-teamChannels# ai-chapter# alerts# backend# confusion-clinic# curiosity_lab# engineering# frontend# general# infra-changes# jiminny-bg# platform-tickets# product launches# random# releases# sofia-office# support# thank-yous# the_people_of jimi…..Direct messagesAneliya Angelova, ...Steliyan GeorgievAdelina Petrova, Ili.... Adelina PetrovaO. Calea Dimitravo→Search Jiminny IncAneliya Angelova, Nikolay Yankov, Steliyan GeorgievMessagesAdd canvas+Nikolay Yankov 10:45 AMпиши кат оя рьннешLukas Kovalik 10:52 AMзабавих се че ми се разбазикаха settings за средипуснах и мина и fail-наима result но e failedзначиREASON_NOT_ENOUGH_ACTIVITIESвиж дали има нещо в OD със този филтьрNikolay Yankov 11:01 AMДобреNikolay Yankov 11:39 AMя рьнни пак LukasLukas Kovalik 11:43 AMготовосьщотоCompetitive pitches беше втория нали такаNikolay Yankov 12:04 PMДа, там има 14 активитита, защо не сработи този пьт?Lukas Kovalik 12:05 PMпак изглежда sequenceгледам гоMessage Aneliya Angelova, Nikolay Yankov, Steliyan Georgiev+Aalal]Support Daily - in 2h 48 m100% <47Tue 14 Apr 12:12:558Today ~...
|
NULL
|
NULL
|
NULL
|
11105
|
|
11104
|
PhpStormFileFV faVsco.jsProject vEditViewNavigateC PhpStormFileFV faVsco.jsProject vEditViewNavigateCodeLaravelRefactor#11894 on JY-18909-automated-reports-ask-iminny K vToolsWindowHelp© JiminnyDebugCommanc© JiminnySetEncryptedTo© JiminnyTokenInfoComn© MakeSlackLiveCoachins© ManageScimForTeam.p(c Malkoanchrorenvironnc Mureu canzercnanner© PhpApm.php© PropagateCoachingFeer© PurgeConferences.php© PurgeSoftDeletedOppor© PurgeSyncBatchesComi© RecalculateDealRisksCa© RemoveDeleteMarkersC© RemoveExpiredNudgesi© RemoveUnusedParticip:© ResetElasticsearch.php© RestoreActivityCrmProv© RestoreActivityTypeCor© SeedActivities.php© SyncActivity.php©Tracklmported.php© UpdateActivitiesAverag© WhichWorkerlsWorkingr>D Scheduling© Kernel.php> D Contracts> M Domain> MDTO> M Emails› _ Enums> D Events> D Exceptions> DJ FFMpeg>D Formats› D Guards› Helpersv UHttp> MAccessTokenProviderv D ControllersV DAPI> D AiCallScoringAiReports> D Deallnsights> D Opportunity> C Page> • Scorecards> D SettingsTeamInsightsnemes> MUserAutomatedRepov DV2© ActivityV2ControlAskAnythingCont© AskJiminnyReporl© DealsV2Controlle:© OnDemandV2Con© PlaylistController.© PlaylistShareContTests passed: 1 (4 minutes ago)© ReportController.php© AutomatedReportsCommand.phpJiminnybeouecommana.ong= custom.log< console EUi= laravel.logA SF [jiminny@localhost]A HS_local [jiminny@localhost]console SlAGiNG© AskJiminnyReportActivityService.phgA console [PROD]© ActivitySearch.pnp© Criteria.php© AutomatedReportsSendCommand.php© AddLayoutEntities.php© Team.php© AutomatedReportsRepository.php X© AutomatedReportsService.phpC CreateHeldActivityEvent.phpOnDemandV2Controller.php© AskJiminnyReportActivityServiceTest.php© HistoryService.php© FilterDefinitionCollection.php© RequestGenerateAskJiminnyReportJobTest.phpCc W .*THAT :(e TrackProvidernstallled-vent.onoQ- activitySearchdeclare(strict_types=1);© CreateActivityLoggedEvent.php• ActivityLogged.php© RequestGenerateAskJiminnyReportJob.phpRequestGenerateReportJob.php(C) AutomatedReport.php© UserPilotActivityListener.php(C) AutomatedReportsCallbackService.phpnamespace Jiminny\Http\Controllers\API\V2;>use...© AutomatedReportResult.phpclass OnDemandV2Controller extends Controllerclass Automacedкeрortskepo o:815 X4 л611141151161171181191211124123use Aurnorizeskeovests/*** Retrieve all standard (non-Ask Jiminny) Mprivate const int DEFAULT_TOP_ACTIVITIES_COUNT = 100;* @param string $sortColumnThe column to* @param string $sortDirection The sort direprivate const array FILTER_KEY_EXCLUDED_PARAMS = [' sequence_number',* @return Collection<AutomatedReport>'page',*/'per_page',12 usagesLniLTe".public function getAllStandardReports(oTTset,string $sortColumn = 'created_at',];string $sortDirection = 'desc'): Collection {...}/*** Retrieve all Ask Liminny reports created&* Oodrdll usernusenIne user Ynos* @param string $sortColumnThe column to* Oparam string $sortDirection The sort direpublic function __construct(private readonly ActivitySearch $eprivate readonly HistoryService $ExtractSurround// =private readonly ProphetService Spropnetservice,private readonly TeamAiContextRepository $teamAiContextRepository,private readonly ActiveStreamsRepository $activeStreamsRepository,privace readonly evencuispaccher gevenculsparcher.orivace readonly Loccerintertace ologder* @return Collection<AutomatedReport>*/14 usagespublic function getAskJiminnyReportsByUser(User $user,string $sortColumn = 'created_at',string ssorcbirection = "desc"): Collection {...J2 usagesprivate function buildSortedQuery(string $sor/*** Get all active and enabled reports with ac* @param string $frequency* dreturh coLcectzon<aucomacedкeрort>78 (gg>12623 usages12271public function getActiveReportsByFrequency(: 157, 0lablf Support Daily • in 2h 48 mAAskJiminnyReportActivityServiceT…Defaults100% C•Tue 14 Apr 12:12:53CascadeFixing ReportControllerAutomated Report MarFixing Ask Jiminny Rep+D..Now let's run the test to verifvwA1X2 A Vtests/Unxt/Servsces/Kiosk/Automate/meports/AskJ1minnyreportActivätyserviceTest-php --no-coveragelou nor oen nolr tler var w nunwarusanprivate function checkAskJiminnyOnAnythingFeature(User $user): ?JsonResponsef.../*** Get top N activity IDs for Ask Jiminny feature based on filters* Othrows ValidationException* Othrows ActivityProviderException*/Command dockerdoster nxe ceockes /kJosk/AuP /ape/a/poras/A5kJ1minyReportActivityServiceTest.php --no-coverageCould not open input file: /app/artisanCommand dockeroocker exec oocker vand ioash -d"cd /var/www&& php artisan testLests unlu services Klosk Aucomaceakeporcs AskJiminnykeportAccivityservicelest.ono =-no-coverade D&l'Could not open input file: artisan• docker exec docker_lamp_1 bash -c "find / -name artisan -maxdepth 6 2>/dev/null | head -5"/home/jiminny/artisan"cd /homee/jiminny && php artisan testtests/nxt/ drvicrs/K2psk/Autonat e"Reports/A3kiminnyReportActivatyserviceTest,php --no-coverage 2261"PASSgetTests\Unit\Services\Kiosk\AutomatedReports\AskJiminnyReportActivityServiceTestfiltersemoty when no resultsperiod date filters1de handtes scalyr flttersids bassess snazer fsequence number to disable first _ 0.025All 8 tests pass. Here's a summary:Root Cause & FixRoot cause: buildRequestParamsFromSearch never set sequence number in the request params, so Criteria::createFromRequest defaulted it to 0Since isFirstRequest() returns true when sequenceNumber === 0, several implicit defaults were silently applied:Activitvourat ionRande → min duration = 1 ilters ouf o-second activitiesiActivityRecorded → only_recorded = 1 (restricts to recorded activities only)OrganiserGroupin → apolies user's derault croup as a tiltelThe frontend URL you noticed uses sequence_number=4, which disables these defaults - explaining why the frontend returned activities but the servicereturee o.Fix: AskJiminnyReportActivityService.php:51—added 'sequence_number' → 1 to the Criteria::createFromRequest merge, ensuring isFirstRequest() returns false and no implicit defaults are injected.lest added: testbetacc1cylasPassesNonzerosequencenumberloDisablerarsckequestberaulus assers that the captured uriteria ob ect nas 1srirstRequest () === false.Öul ..Vew alllipublic function getContextForAskAnythingByFilter(Request $request, ElasticActivityRepositorItlle wiun changesvapp/Services/Kiosk/AutomatedReports/D AskJiminnyReportActivityService.php +1 -1Reject allAccept allprivate function hasChangedContextFilter(Request $request, User $user): boolf...}Explain it to me again. Why is there issue with that? Where is it expected and wy do l need to fork with that. How is it used [EMAIL]< CodeClaude Sonnet 4.6W Windsurf Teams48:0014 charsuir-o( 4 spaces...
|
NULL
|
NULL
|
NULL
|
11104
|
|
11103
|
+SlackEDHomeDMSActivityFilesLater..•More+FileEditV +SlackEDHomeDMSActivityFilesLater..•More+FileEditViewGoHistoryWindowHelpJiminny ...# Starredplatform-inner-teamChannels# ai-chapter# alerts# backend# confusion-clinic# curiosity_lab# engineering# frontend# general# infra-changes# jiminny-bg# platform-tickets# product launches# random# releases# sofia-office# support# thank-yous# the_people_of jimi…..Direct messagesAneliya Angelova, ...Steliyan GeorgievAdelina Petrova, Ili.... Adelina PetrovaO. Calea Dimitravo→Search Jiminny IncAneliya Angelova, Nikolay Yankov, Steliyan GeorgievMessagesAdd canvas+Nikolay Yankov 10:45 AMпиши кат оя рьннешLukas Kovalik 10:52 AMзабавих се че ми се разбазикаха settings за средипуснах и мина и fail-наима result но e failedзначиREASON_NOT_ENOUGH_ACTIVITIESвиж дали има нещо в OD със този филтьрNikolay Yankov 11:01 AMДобреNikolay Yankov 11:39 AMя рьнни пак LukasLukas Kovalik 11:43 AMготовосьщотоCompetitive pitches беше втория нали такаNikolay Yankov 12:04 PMДа, там има 14 активитита, защо не сработи този пьт?Lukas Kovalik 12:05 PMпак изглежда sequenceгледам гоMessage Aneliya Angelova, Nikolay Yankov, Steliyan Georgiev+Aalal]Support Daily - in 2h 48 m100% <47Tue 14 Apr 12:12:5386 0Today ~...
|
NULL
|
NULL
|
NULL
|
11103
|
|
11102
|
PhpStormFileFV faVsco.jsProject vEditViewNavigateC PhpStormFileFV faVsco.jsProject vEditViewNavigateCodeLaravelRefactor#11894 on JY-18909-automated-reports-ask-liminny k vToolsWindowHelp© JiminnyDebugCommanc©JiminnySetEncryptedTo© JiminnyTokenInfoComn© MakeSlackLiveCoachins© ManageScimForTeam.p(c Malkoanchrorenvironnc Mureu canzercnanner© PhpApm.php© PropagateCoachingFeer© PurgeConferences.php© PurgeSoftDeletedOppor© PurgeSyncBatchesComi© RecalculateDealRisksCa© RemoveDeleteMarkersC© RemoveExpiredNudgesi© RemoveUnusedParticip:© ResetElasticsearch.php© RestoreActivityCrmProv© RestoreActivityTypeCor© SeedActivities.php© SyncActivity.php©Tracklmported.php© UpdateActivitiesAverag© WhichWorkerlsWorkingr> D Scheduling© Kernel.php> D Contracts> M Domain> MDTO> M Emails› _ Enums> D Events> D Exceptions> DJ FFMpeg>D Formats› D Guards› Helpersv UHttp> MAccessTokenProviderv D ControllersV DAPI> DAiCallScoringAiReports> D Deallnsights> D Opportunity> C Page> • Scorecards> D SettingsTeamInsightsnemes> MUserAutomatedRepov DV2© ActivityV2ControlAskAnythingCont© AskJiminnyReporl© DealsV2Controlle:© OnDemandV2Con© PlaylistController.© PlaylistShareCont© ReportController.php© AutomatedReportsCommand.phpJiminnybeouecommana.ong= custom.log< console LUl= laravel.logA SF [jiminny@localhost]A HS_local [jiminny@localhost]console SlAGiNG© AskJiminnyReportActivityService.phg© AutomatedReportsSendCommand.php© AddLayoutEntities.php© Team.php© AutomatedReportsRepository.php X© AutomatedReportsService.phpC CreateHeldActivityEvent.phpOnDemandV2Controller.php© AskJiminnyReportActivityServiceTest.phpsrono© HistoryService.phpA console [PROD]© ActivitySearch.pnp© Criteria.php© FilterDefinitionCollection.php© RequestGenerateAskJiminnyReportJobTest.php(e TrackProvidernstallled-vent.onodeclare(strict_types=1);© CreateActivityLoggedEvent.php© UserPilotActivityListener.php• ActivityLogged.phpAutomatedReportsCallbackService.php© RequestGenerateAskJiminnyReportJob.phpRequestGenerateReportJob.php© AutomatedReportResult.php(C) AutomatedReport.phpnamespace Jiminny\Http\Controllers\API\V2;>use...class OnDemandV2Controller extends Controllerclass Automacedкeрortskepo o:A15 X4 ^6175761141151161171181191211124use Aurnorizeskeovests/*** Retrieve all standard (non-Ask Jiminny) Mprivate const int DEFAULT_TOP_ACTIVITIES_COUNT = 100;* @param string $sortColumnThe column to* @param string $sortDirection The sort direprivate const array FILTER_KEY_EXCLUDED_PARAMS = [' sequence_number',* @return Collection<AutomatedReport>'page',*/'per_page',12 usagesLniLTe".public function getAllStandardReports(oTTset,string $sortColumn = 'created_at',];string $sortDirection = 'desc'): Collection {...}/*** Retrieve all Ask Liminny reports created&* Oodrdll usernusenIne user Ynos* @param string $sortColumnThe column to* Oparam string $sortDirection The sort direpublic function __construct(private readonly ActivitySearch IctivitySearch,private readonly HistoryService ShistoryService,private readonly ProphetService SprophetService,private readonly TeamAiContextRepository $teamAiContextRepository,private readonly ActiveStreamsRepository $activeStreamsRepository,privace readonly evencuispaccher gevenculsparcher.orivace readonly Loccerintertace ologder* @return Collection<AutomatedReport>*/14 usagespublic function getAskJiminnyReportsByUser(User $user,string $sortColumn = 'created_at',string ssorcbirection = "desc"): Collection {...J2 usagesprivate function buildSortedQuery(string $sor/*** Get all active and enabled reports with ac* @param string $frequency78 (gg>126* dreturh coLcectzon<aucomacedкeрort>23 usages12271public function getActiveReportsByFrequency(: 157lests passed: l(s minutes ago, 0lablf Support Daily • in 2h 48 mAAskJiminnyReportActivityServiceT…Defaults100% C•Tue 14 Apr 12:12:50CascadeFixing ReportControllerAutomated Report MarFixing Ask Jiminny Rep+D..Now let's run the test to verifvA1 X2 ^wprivate function checkAskJiminnyOnAnythingFeature(User $user): ?JsonResponsef.../*** Get top N activity IDs for Ask Jiminny feature based on filters* Othrows ValidationException* Othrows ActivityProviderException*/tests/Unxt/Servsces/Kiosk/Automate/meports/AskJ1minnyreportActivätyserviceTest-php --no-coveragelou nor oen nolr tler var w nunwarusanCommand dockerdoster nxe ceockes /kJosk/AuP /ape/a/poras/A5kJ1minyReportActivityServiceTest.php --no-coverageCould not open input file: /app/artisanCommand dockeroocker exec oocker vand ioash -c"cd /var/www&& php artisan testLests unlu services Klosk Aucomaceakeporcs AskJiminnykeportAccivityservicelest.ono =-no-coverade D&l'Could not open input file: artisan• docker exec docker_lamp_1 bash -c "find / -name artisan -maxdepth 6 2>/dev/null | head -5"/home/jiminny/artisan"cd /homee/jiminny && php artisan testtests/nxt/ drvicrs/K2psk/Autonat e"Reports/A3kiminnyReportActivatyserviceTest,php --no-coverage 2261"PASSgetTests\Unit\Services\Kiosk\AutomatedReports\AskJiminnyReportActivityServiceTestfiltersemoty when no resultsperiod date filters1de handtes scalyr flttersids bassess snazero fsequence number to disable first ._. 0.025All 8 tests pass. Here's a summary:Root Cause & FixKoOL cause: bu1 Ldkequestraramst romsearch never set sequence number In the request params, so criterla::creater romkequest delaulted lt to 0Since isFirstRequest() returns true when sequenceNumber === 0, several implicit defaults were silently applied:Activitvourat ionRande → min duration = 1 ilters ouf o-second activitiesiActivityRecorded → only_recorded = 1 (restricts to recorded activities only)OrganiserGroupin → apolies user's derault croup as a tiltelThe frontend URL you noticed uses sequence_number=4, which disables these defaults - explaining why the frontend returned activities but the servicereturee o.Fix: AskJiminnyReportActivityService.php:51—added 'sequence_number' → 1 to the Criteria::createFromRequest merge, ensuring isFirstRequest() returns false and no implicit defaults are injected.lest added: testbetacc1cylasPassesNonzerosequencenumberloDisablerarsckequestberaulus assers that the captured uriteria ob ect nas 1srirstRequest () === false.Oul .Vew alllipublic function getContextForAskAnythingByFilter(Request $request, ElasticActivityRepositorItlle wiun changesvapp/Services/Kiosk/AutomatedReports/D AskJiminnyReportActivityService.php +1 -1Reject allAccept allprivate function hasChangedContextFilter(Request $request, User $user): boolf...}Explain it to me again. Why is there issue with that? Where is it expected and wy do l need to fork with that. How is it used [EMAIL]‹> CodeClaude Sonnet 4.6Winasun leams55:8uir-o( 4 spaces...
|
NULL
|
NULL
|
NULL
|
11102
|
|
11101
|
+SlackEDHomeDMSActivityFilesLater..•More+FileEditV +SlackEDHomeDMSActivityFilesLater..•More+FileEditViewGoHistoryWindowHelpJiminny ...# Starredplatform-inner-teamChannels# ai-chapter# alerts# backend# confusion-clinic# curiosity_lab# engineering# frontend# general# infra-changes# jiminny-bg# platform-tickets# product launches# random# releases# sofia-office# support# thank-yous# the_people_of jimi…..Direct messagesAneliya Angelova, ...Steliyan GeorgievAdelina Petrova, Ili.... Adelina PetrovaO. Calea Dimitravo→Search Jiminny IncAneliya Angelova, Nikolay Yankov, Steliyan GeorgievMessagesAdd canvas+Nikolay Yankov 10:45 AMпиши кат оя рьннешLukas Kovalik 10:52 AMзабавих се че ми се разбазикаха settings за средипуснах и мина и fail-наима result но e failedзначиREASON_NOT_ENOUGH_ACTIVITIESвиж дали има нещо в OD със този филтьрNikolay Yankov 11:01 AMДобреNikolay Yankov 11:39 AMя рьнни пак LukasLukas Kovalik 11:43 AMготовосьщотоCompetitive pitches беше втория нали такаNikolay Yankov 12:04 PMДа, там има 14 активитита, защо не сработи този пьт?Lukas Kovalik 12:05 PMпак изглежда sequenceгледам гоMessage Aneliya Angelova, Nikolay Yankov, Steliyan Georgiev+Aalal]Support Daily - in 2h 48 m100% <47Tue 14 Apr 12:12:5086 0Today ~...
|
NULL
|
NULL
|
NULL
|
11101
|
|
11100
|
PhpStormFileEditViewNavigateCodeLaravelRefactorToo PhpStormFileEditViewNavigateCodeLaravelRefactorToolsWindowHelpFV faVsco.js#11894 on JY-18909-automated-reports-ask-iminny K vProject v© ReportController.phpJiminnybeouecommana.ong© AutomatedReportsCommand.php© AutomatedReportsSendCommand.php© AddLayoutEntities.php© Team.php© AutomatedReportsRepository.php X© AutomatedReportsService.phpC CreateHeldActivityEvent.php, 0lablf Support Daily • in 2h 48 mA100% C•Tue 14 Apr 12:12:48AskJiminnyReportActivityServiceT…Defaults© JiminnyDebugCommanc©JiminnySetEncryptedTo© JiminnyTokenInfoComn© MakeSlackLiveCoachins© ManageScimForTeam.p(c Malkoanchrocnvronnlc Mureu canzercnanner© PhpApm.php© PropagateCoachingFeer© PurgeConferences.php© PurgeSoftDeletedOppor© PurgeSyncBatchesComiC RecalculateDealRisksCa© RemoveDeleteMarkersC© RemoveExpiredNudgesi© RemoveUnusedParticip:© ResetElasticsearch.php© RestoreActivityCrmProv© RestoreActivityTypeCor© SeedActivities.php© SyncActivity.php©Tracklmported.php© UpdateActivitiesAverag© WhichWorkerlsWorkingr> D Scheduling© Kernel.php> D Contracts> M Domain> MDTO> M Emails› _ Enums> D Events> D Exceptions> DJ FFMpeg› D Formats› D Guards› Helpersv UHttp> MAccessTokenProviderv D ControllersV DAPI> D AiCallScoringAiReports> D Deallnsights> D Opportunity> C Page> • Scorecards> D SettingsTeamInsightsnemes> MUserAutomatedRepov DV2© ActivityV2ControlAskAnythingCont© AskJiminnyReporl© DealsV2Controlle:© OnDemandV2Con© PlaylistController.© PlaylistShareContlests passed: l(s minutes ago= custom.log< console EUi= laravel.logA SF [jiminny@localhost]A HS_local [jiminny@localhost]A console [PROD]console SlAGiNG© AskJiminnyReportActivityService.phg© ActivitySearch.pnp© Criteria.phpCascadeFixing ReportControllerAutomated Report MarFixing Ask Jiminny Rep+D..(e TrackProvidernstallled-vent.onoOnDemandV2Controller.php© HistoryService.php© FilterDefinitionCollection.php© AskJiminnyReportActivityServiceTest.php© RequestGenerateAskJiminnyReportJobTest.phpsronodeclare(strict_types=1);Now let's run the test to verifvA1 X2 ^w© CreateActivityLoggedEvent.php© UserPilotActivityListener.php• ActivityLogged.php(C) AutomatedReportsCallbackService.php© RequestGenerateAskJiminnyReportJob.phpRequestGenerateReportJob.php© AutomatedReportResult.php(C) AutomatedReport.phpclass Automacedкeрortskepo o:A15 X4 ^namespace Jiminny\Http\Controllers\API\V2;>use...class OnDemandV2Controller extends Controller61use AurnorizeskeQvests/*** Retrieve all standard (non-Ask Jiminny) Mprivate const int DEFAULT_TOP_ACTIVITIES_COUNT = 100;* @param string $sortColumnThe column to* @param string $sortDirection The sort direprivate const array FILTER_KEY_EXCLUDED_PARAMS = [' sequence_number',* @return Collection<AutomatedReport>'page','per_page',12 usages'limit',public function getAllStandardReports(oTTset,string $sortColumn = 'created_at',];string $sortDirection = 'desc'): Collection {...}/*** Retrieve all Ask Liminny reports created&* Oodrdll usernusenIne user Ynos* @param string $sortColumnThe column to* Oparam string $sortDirection The sort direpublic function __construct(private readonly ActivitySearch $actfivitySearch,private readonly HistoryService ShistoryService,private readonly ProphetService SprophetService,private readonly TeamAiContextRepository $teamAiContextRepository,private readonly ActiveStreamsRepository $activeStreamsRepository,private readonly eventulspaccher pevencuispaccher,orivace readonly Loccerintertace ologder* @return Collection<AutomatedReport>*/14 usagespublic function getAskJiminnyReportsByUser(User $user,string $sortColumn = 'created_at',string ssorcbirection = "desc"): Collection {...J2 usagesprivate function buildSortedQuery(string $sor/*** Get all active and enabled reports with al* @param string $frequency* check if the usen's tean has the ASK. JTMTMIV, ON ANYTHTING featune enabted*/private function checkAskJiminnyOnAnythingFeature(User $user): ?JsonResponse{..3* Get top N activity IDs for Ask Jiminny feature based on filters* Othrows ValidationException* ethrous ActivityprovidenExceptiontests/Unxt/Servsces/Kiosk/Automate/meports/AskJ1minnyreportActivätyserviceTest-php --no-coveragecould not open input Tile: /var/www/ncml/artisanCommand dockerdoster nxe ceockes /kJosk/AuP /ape/a/poras/A5kJ1minyReportActivityServiceTest.php --no-coverageCould not open input file: /app/artisanCommand docker•cocker exec oocker land ioash —d"cd /var/www&& php artisan testLests unlu services Klosk Aucomaceakeporcs AskJiminnykeportAccivityservicelest.ono =-no-coverade D&l'Could not open input file: artisan• docker exec docker_lamp_1 bash -c "find / -name artisan -maxdepth 6 2>/dev/null | head -5"/home/jiminny/artisan"cd /homee/jiminny && php artisan testtests/nxt/sdrvicrs/K2psk/Autonat e"Reports/A3kiminnyReportActivatyserviceTest.php --no-coverage 2261PASSgetTests\Unit\Services\Kiosk\AutomatedReports\AskJiminnyReportActivityServiceTestfiltersemoty when no resultsE tatt tnt hperiod date filtersids bassess snazero fsequence number to disable first ._. 0.025All 8 tests pass. Here's a summary:Root Cause & FixRoot cause: buildRequestParamsFromSearch never set sequence number in the request params, so Criteria::createFromRequest defaulted it to 0Since isFirstRequest() returns true when sequenceNumber === 0, several implicit defaults were silently applied:Activitvourat ionRande → min duration = 1 ilters ouf o-second activitiesiActivityRecorded → only_recorded = 1 (restricts to recorded activities only)OrganiserGroupin → apolies user's derault croup as a tiltelThe frontend URL you noticed uses sequence_number=4, which disables these defaults - explaining why the frontend returned activities but the servicereturned O.Fix: AskJiminnyReportActivityService.php:51—added 'sequence_number' → 1 to the Criteria::createFromRequest merge, ensuring isFirstRequest() returns false and no implicit defaults are injected.lest added: testbetacc1cylasPassesNonzerosequencenumberloDisablerarsckequestberaulus assers that the captured uriteria ob ect nas 1srirstRequest () === false.Oul .1141151161171181191211124123* dreturh coLcectzon<aucomaredкeport.23 usagespublic function getActiveReportsByFrequency(s78 (gg>public function getContextForAskAnythingByFilter(Request $request, ElasticActivityRepositorItlle wiun changesv126app/Services/Kiosk/AutomatedReports/D AskJiminnyReportActivityService.php +1 -1127private function hasChangedContextFilter(Request $request, User $user): boolf...}Explain it to me again. Why is there issue with that? Where is it expected and wy do l need to fork with that. How is it used [EMAIL]‹> CodeClaude Sonnet 4.6Vew allliReject allAccept allW Windsurf Teams48:45uir-o( 4 spaces...
|
NULL
|
NULL
|
NULL
|
11100
|
|
11099
|
+SlackEDHomeDMSActivityFilesLater..•More+FileEditV +SlackEDHomeDMSActivityFilesLater..•More+FileEditViewGoHistoryWindowHelpJiminny ...# Starredplatform-inner-teamChannels# ai-chapter# alerts# backend# confusion-clinic# curiosity_lab# engineering# frontend# general# infra-changes# jiminny-bg# platform-tickets# product_launches# random# releases# sofia-office# support# thank-yous# the_people_of jimi…..Direct messagesAneliya Angelova, ...Steliyan GeorgievAdelina Petrova, Ili.... Adelina PetrovaO. Calea Dimitravo→Search Jiminny IncAneliya Angelova, Nikolay Yankov, Steliyan GeorgievMessagesAdd canvas+Nikolay Yankov 10:45 AMпиши кат оя рьннешLukas Kovalik 10:52 AMзабавих се че ми се разбазикаха settings за средипуснах и мина и fail-наима result но e failedзначиREASON_NOT_ENOUGH_ACTIVITIESвиж дали има нещо в OD със този филтьрNikolay Yankov 11:01 AMДобреNikolay Yankov 11:39 AMя рьнни пак LukasLukas Kovalik 11:43 AMготовосьщотоCompetitive pitches беше втория нали такаNikolay Yankov 12:04 PMДа, там има 14 активитита, защо не сработи този пьт?Lukas Kovalik 12:05 PMпак изглежда sequenceгледам гоMessage Aneliya Angelova, Nikolay Yankov, Steliyan Georgiev+Aalal]Support Daily - in 2h 48 m100% <47Tue 14 Apr 12:12:488Today ~...
|
NULL
|
NULL
|
NULL
|
11099
|
|
11098
|
+SlackEDHomeDMSActivityFilesLater..•More+FileEditV +SlackEDHomeDMSActivityFilesLater..•More+FileEditViewGoHistoryWindowHelpJiminny ...# Starredplatform-inner-teamChannels# ai-chapter# alerts# backend# confusion-clinic# curiosity_lab# engineering# frontend# general# infra-changes# jiminny-bg# platform-tickets# product launches# random# releases# sofia-office# support# thank-yous# the_people_of jimi…..Direct messagesAneliya Angelova, ...Steliyan GeorgievAdelina Petrova, Ili.... Adelina PetrovaO. Calea Dimitravo→Search Jiminny IncAneliya Angelova, Nikolay Yankov, Steliyan GeorgievMessagesAdd canvas+Nikolay Yankov 10:45 AMпиши кат оя рьннешLukas Kovalik 10:52 AMзабавих се че ми се разбазикаха settings за средипуснах и мина и fail-наима result но e failedзначиREASON_NOT_ENOUGH_ACTIVITIESвиж дали има нещо в OD със този филтьрNikolay Yankov 11:01 AMДобреNikolay Yankov 11:39 AMя рьнни пак LukasLukas Kovalik 11:43 AMготовосьщотоCompetitive pitches беше втория нали такаNikolay Yankov 12:04 PMДа, там има 14 активитита, защо не сработи този пьт?Lukas Kovalik 12:05 PMпак изглежда sequenceгледам гоMessage Aneliya Angelova, Nikolay Yankov, Steliyan Georgiev+Aalal]Support Daily - in 2h 48 m100% <47Tue 14 Apr 12:12:458Today ~...
|
NULL
|
NULL
|
NULL
|
11098
|
|
11097
|
PhpStormFileEditViewNavigateCodeLaravelRefactorToo PhpStormFileEditViewNavigateCodeLaravelRefactorToolsWindowHelpFV faVsco.js#11894 on JY-18909-automated-reports-ask-liminny k vProject v© ReportController.phpJiminnybeouecommana.ong© AutomatedReportsCommand.php© AutomatedReportsSendCommand.php© AddLayoutEntities.php© Team.php© AutomatedReportsRepository.php X© AutomatedReportsService.phpC CreateHeldActivityEvent.php, 0lablf Support Daily • in 2h 48 mA100% C•Tue 14 Apr 12:12:44AskJiminnyReportActivityServiceT…Defaults© JiminnyDebugCommanc©JiminnySetEncryptedTo© JiminnyTokenInfoComn© MakeSlackLiveCoachins© ManageScimForTeam.p(c Malkoanchrorenvironnc Mureu canzercnanner© PhpApm.php© PropagateCoachingFeer© PurgeConferences.php© PurgeSoftDeletedOppor© PurgeSyncBatchesComi© RecalculateDealRisksCa© RemoveDeleteMarkersC© RemoveExpiredNudgesi© RemoveUnusedParticip:© ResetElasticsearch.php© RestoreActivityCrmProv© RestoreActivityTypeCor© SeedActivities.php© SyncActivity.php©Tracklmported.php© UpdateActivitiesAverag© WhichWorkerlsWorkingr> D Scheduling© Kernel.php> D Contracts> M Domain> MDTO> M Emails› _ Enums> D Events> D Exceptions> DJ FFMpeg>D Formats› D Guards› Helpersv UHttp> MAccessTokenProviderv D ControllersV DAPI> D AiCallScoringAiReports> D Deallnsights> D Opportunity> C Page> • Scorecards> D SettingsTeamInsightsnemes> MUserAutomatedRepov DV2© ActivityV2ControlAskAnythingCont© AskJiminnyReporl© DealsV2Controlle:© OnDemandV2Con© PlaylistController.© PlaylistShareContlests passed:1 (s minutes ago= custom.log= laravel.logA SF [jiminny@localhost]A HS_local [jiminny@localhost]A console [PROD]< console EUiconsole SlAGiNGAskJIminnykeporiAcuivilyservice.ong© ActivitySearch.pnp© Criteria.phpCascadeFixing ReportControllerAutomated Report MarFixing Ask Jiminny Rep+D ...(e) TrackProvidernstallled-vent.onoOnDemandV2Controller.php© HistoryService.php© FilterDefinitionCollection.php© AskJiminnyReportActivityServiceTest.php© RequestGenerateAskJiminnyReportJobTest.phpsronodeclare(strict_types=1);Nowersrunthe esto vertvA1 X2 ^© CreateActivityLoggedEvent.php© UserPilotActivityListener.php• ActivityLogged.php(C) AutomatedReportsCallbackService.php© RequestGenerateAskJiminnyReportJob.phpRequestGenerateReportJob.php© AutomatedReportResult.php(C) AutomatedReport.phpclass Automacedкeрortskepo o:815 X4 лnamespace Jiminny\Http\Controllers\API\V2;>use...class OnDemandV2Controller extends Controlleruse AurnorizeskeQvests/*** Retrieve all standard (non-Ask Jiminny) Mprivate const int DEFAULT_TOP_ACTIVITIES_COUNT = 100;tests/unxt/Servzces/Kiosk/Automate/keports/AskJ1minyRepprtActivityServiceTest.php --no-coverageloul nor oen ndlr Tler var ww nunbarusanCommand dockerdoster nxe ceockes /kJosk/AuP /ape/a/poras/A5kJ1minyReportActivityServiceTest. php --no-coverageCould not open input file: /app/artisanCommand docker•cocker exec oocker vand ioash —dSid php artisan testLests unlu services Klosk Aucomaceakeporcs AskJiminnykeportAccivityservicelest.ono =-no-coverade D&l'Could not open input file: artisan* @param string $sortColumnThe column to* @param string $sortDirection The sort direprivate const array FILTER_KEY_EXCLUDED_PARAMS = [• docker exec docker lamo 1 bash -c "find / -name artisan -maxdenth 6 2>/dev/null | head -5"61' sequence_number',/home/jiminny/artisan* @return Collection<AutomatedReport>'page',*/'per_page',12 usagesLniLTe".iminny && php artisan testpublic function getAllStandardReports(oTTset,•dests/unxe/servkces/K1osk/AusomatedReports/AskJ1maynyReportActiVatyServiceTest.php --no-coverage 2>&1"string $sortColumn = 'created_at',];PASSstring $sortDirection = 'desc'getTests\Unit\Services\Kiosk\AutomatedReports\AskJiminnyReportActivityServiceTestreturns): Collection {...}public function __construct(a fittersemoty when no resultsperiod date filters/**private readonly Activitysrch $activitySearch,1de handtes scalyr fltters75* Retrieve all Ask Liminny reports created&private readonly HistoryService ShistoryService,get activity ids hassees sn zero sequence number to disable first r._ 0.025private readonly ProphetService SprophetService,* Oodrdll usernusenIne user Ynosprivate readonly TeamAiContextRepository $teamAiContextRepository,All 8 tests pass. Here's a summary:* @param string $sortColumnThe column toprivate readonly ActiveStreamsRepository $activeStreamsRepository,* Oparam string $sortDirection The sort direprivace readonly evencuispaccher gevenculsparcher.Root Cause & FixKoOL cause: bu1 Ldkequestraramst romsearch never set sequence number In the request params, so criterla::creater romkequest delaulted lt to 0orivace readonly Loccerintertace ologder* @return Collection<AutomatedReport>) f...3Since isFirstRequest() returns true when sequenceNumber === 0, several implicit defaults were silently applied:*/Activitvourat ionRande → min duration = 1 ilters ouf o-second activitiesi14 usagespublic function getAskJiminnyReportsByUser(* Cheok 1f the user's tean has the ASK. JTMIMVYLON ANYTHTNG featune enabtedActivityRecorded → only_recorded = 1 (restricts to recorded activities only)OrganiserGroupin → apolies user's derault croup as a tilterUser $user,*/The frontend URL you noticed uses sequence_number=4, which disables these defaults - explaining why the frontend returned activities but the servicestring $sortColumn = 'created_at',returee o.string ssorcbirection = "desc"private function checkAskJiminnyOnAnythingFeature(User $user): ?JsonResponse{..3Fix: AskJiminnyReportActivityService.php:51—added 'sequence_number' → 1 to the Criteria::createFromRequest merge, ensuring isFirstReque): Collection {...Jst() returns false and no implicit defaults are injected.lest added: testbetacc1cylasPassesNonzerosequencenumberloDisablerarsckequestberaulus assers that the captured uriteria ob ect nas 1srirs2 usages* Get top N activity IDs for Ask Jiminny feature based on filterstRequest () === false.private function buildSortedQuery(string $sorÖul ..114* Othrows ValidationException115/**116* Get all active and enabled reports with al* ethravs AotävityPnovzdenexcept2on117118* @param string $frequency78 (gg>public function getContextForAskAnythingByFilter(Request $request, ElasticActivityRepositorVew allliItlle win changesv119126app/Services/Kiosk/AutomatedReports/D AskJiminnyReportActivityService.php +1 -1* dreturh coLcectzon<aucomaredкeport.Reject allAccept all121127private function hasChangedContextFilter(Request $request, User $user): boolf...}Explain it to me again. Why is there issue with that? Where is it expected and wy do l need to fork with that. How is it used in23 usages1571124public function getActiveReportsByFrequency([EMAIL]<> Code123Claude Sonnet 4.6W Windsurf Teams498:48uir-o( 4 spaces...
|
NULL
|
NULL
|
NULL
|
11097
|
|
11096
|
+SlackEDHomeDMSActivityFilesLater..•More+FileEditV +SlackEDHomeDMSActivityFilesLater..•More+FileEditViewGoHistoryWindowHelpJiminny ...# Starredplatform-inner-teamChannels# ai-chapter# alerts# backend# confusion-clinic# curiosity_lab# engineering# frontend# general# infra-changes# jiminny-bg# platform-tickets# product_launches# random# releases# sofia-office# support# thank-yous# the_people_of jimi…..Direct messagesAneliya Angelova, ...Steliyan GeorgievAdelina Petrova, Ili.... Adelina PetrovaO. Calea Dimitravo→Search Jiminny IncAneliya Angelova, Nikolay Yankov, Steliyan GeorgievMessagesAdd canvas+Nikolay Yankov 10:45 AMпиши кат оя рьннешLukas Kovalik 10:52 AMзабавих се че ми се разбазикаха settings за средипуснах и мина и fail-наима result но e failedзначиREASON_NOT_ENOUGH_ACTIVITIESвиж дали има нещо в OD със този филтьрNikolay Yankov 11:01 AMДобреNikolay Yankov 11:39 AMя рьнни пак LukasLukas Kovalik 11:43 AMготовосьщотоCompetitive pitches беше втория нали такаNikolay Yankov 12:04 PMДа, там има 14 активитита, защо не сработи този пьт?Lukas Kovalik 12:05 PMпак изглежда sequenceгледам гоMessage Aneliya Angelova, Nikolay Yankov, Steliyan Georgiev+Aalal]Support Daily - in 2h 48 m100% <47Tue 14 Apr 12:12:448Today ~...
|
NULL
|
NULL
|
NULL
|
11096
|
|
11095
|
PhpStormFileEditViewNavigateCodeLaravelRefactorFV PhpStormFileEditViewNavigateCodeLaravelRefactorFV faVsco.js v#11894 on JY-18909-automated-reports-ask-iminny K vProject vToolsWindowHelp© JiminnyDebugCommanc©JiminnySetEncryptedTo© JiminnyTokenInfoComn© MakeSlackLivecoaching© Managescim-orleam.p(c Malkoanchrocnvronnl© MuteOrganizerChannel.© PhpApm.php© PropagateCoachingFeer© PurgeConferences.php© PurgeSoftDeletedOppor© PurgeSyncBatchesComiC RecalculateDealRisksCa© RemoveDeleteMarkersC© RemoveExpiredNudgesi© RemoveUnusedParticip:C ResetElasticSearch.php© RestoreActivityCrmProv© RestoreActivityTypeCor© SeedActivities.php© SyncActivity.php©Tracklmported.php© UpdateActivitiesAverag© WhichWorkerlsWorkingr> Scheduling© Kernel.phpM Contracts> M Domain> MDTO> M Emails› _ Enums> D Events> D Exceptions> DJ FFMpeg>D Formats› D Guards› C Helpersv UHttp> MAccessTokenProviderv D Controllersv MAPI> D AiCallScoringAiReports> D Deallnsights> D Opportunity> C Page> • Scorecards> D SettingsTeamInsightsnemes> MUserAutomatedRepov DV2C ACIMINVACOnTOAskAnythingCont© AskJiminnyReporl© DealsV2Controlle:© OnDemandV2Con© PlaylistController.© PlaylistShareContTests passed: 1 (3 minutes ago)© ReportController.php© AutomatedReportsCommand.phpJiminnybeouecommana.ong= custom.log= laravel.logA SF [jiminny@localhost]A HS_local [jiminny@localhost]A console [PROD]< console EUiconsole SlAGiNGAskJIminnykepor Acuivilyservice.ongACuiVilysearch.onp© AutomatedReportsSendCommand.php© AddLayoutEntities.php© Team.php© AutomatedReportsRepository.php X© AutomatedReportsService.phpCrealenelaAcuviyevent.onoOnDemandV2Controller.php© HistoryService.php© FilterDefinitionCollection.php© Criteria.php© AskJiminnyReportActivityServiceTest.phpC) RequestGenerateAskJiminnyReportJobTest.phpclass OnDemandV2Controller extends Controller41 M2 ^(e TrackProvidernstallled-vent.ono241public function askAnything(OnDemandAskAnythingRequest $request): StreamedResponse |JsonResp→ ounouLbala lllessauer© CreateActivityLoggedEvent.php© UserPilotActivityListener.php262'callIds' => $this->historyService->getContextIds($user,identifier: HistoryServic263'history' => $this->historyService->getHistory($user,identifier: HistoryService::• ActivityLogged.phpAutomatedReportsCallbackService.php264C RequestGenerateAskJiminnyReportJob.php265266$teamAiContext = $this->teamAiContextRepository->getByTeamId($user->getTeamId());RequestGenerateReportJob.php© AutomatedReportResult.phpif ($teamAiContext?->getPrompt() !== null) {(C) AutomatedReport.php268"reouescvaral'teanaucontext' = "reanazcontext->deurronotoclass Automacedкeрortskepo o:A15 X4 Av20%61627593114115116117118119121123LI4/**273* Retrieve all standard (non-Ask Jiminny) M274* @param string $sortColumnThe column to276*dparam string ssortulrection ine sort dire277* @return Collection<AutomatedReport>.278279*/12 usagespublic function getAllStandardReports(string $sortColumn = 'created_at',string $sortDirection = 'desc'): Collection {..[PHONE]84285/**286287* Retrieve all Ask Liminny reports created A288* Oodrdll usernusenIne user Ynos* @param string $sortColumnThe column te290* Oparam string $sortDirection The sort dire2911475* @return Collection<AutomatedReport>294*/-29514 usages296public function getAskJiminnyReportsByUser(User $user,298string $sortColumn = 'created_at',string ssorcbirection = "desc"): Collection {...J300301—302Z usagesprivate function buildSortedQuery(string $sor]305504/**—305306* Get all active and enabled reports with ac—307308* @param string $frequency309— 310* dreturn cocLectron<Aucomacedкeрort»31131223 usagespublic function getActiveReportsByFrequency(s)314$this->historyService->appendToUserHistory($user,identifier: HistoryService::0N_DEMAND_SERVICE,$inputData[ 'message']):$this->historyService->appendToEventHistory(user: $user,identifier: HistoryService::0N_DEMAND_SERVICE,type: HistoryService::EVENT_IN_PROGRESS_TYPE):$streamRequest = StreamRequest: :onDemandLevel($requestData);// Track active stream in Redis$this->activeStreamsRepository->start($user->getId(),$streamRequest->getId(),ttlSeconds: $streamRequest->getConnectTimeout() + $streamRequest->getReadTimeou):rerur uns-porooneroeru ce-poerotreanecuraoorteoresconsestreankeovest, "strealikecuest.onCompleted: function (string $assistantResponse,bool $clientAborted,bool $hadError,) use ($user, $streamRequest) {// Remove in-progress eventSthis->historyService->removeLastEventMessageByType($user,identifier: HistoryService: : ON_DEMAND_SERVICE,type: HistorvService::EVENT IN PROGRESS TYPE// Save to history if backend completed successfully (even if client discor// Only skip saving if there was an actual error during streamingif (! $hadError && ! empty(trim($assistantResponse))) {$this->historyService->appendToSystemHistory($user,identifier: HistoryService::0N_DEMAND_SERVICE,$assistantResponse,, 0lablf Support Daily • in 2h 48 mAAskJiminnyReportActivityServiceT…Defaults100% C•Tue 14 Apr 12:12:35CascadeFixing ReportControllerAutomated Report MarFixing Ask Jiminny Rep+D ..Now let's run the test to verifvdesker nte/ sockces/k.osk/AuPowar/orts/artman yeportActivityserviceTest.php --no-coverageloul nor oen Indlr tler var w nunwarusandoster nxe ceockes /kJosk/AuP /ape/a/poras/A5kJ1minyReportActivityServiceTest. php --no-coverageCould not open input file: /app/artisanCommand dockerocker exec oocker land 1oash -dSid php artisan testLests unlu services Klosk Aucomaceakeporcs AskJiminnykeportAccivityservicelest.ono =-no-coverade D&l'Could not open input file: artisan• docker exec docker lamp 1 bash -c "find / -name artisan -maxdeoth 6 2>/dev/null | head -5"/home/jiminny/artisan"cd /homeiminny && php artisan test•dests/unxe/servkces/K1osk/AusomatedReports/AskJ1maynyReportActiVatyServiceTest.php --no-coverage 2>&1"PASSTests\Unit\Services\Kiosk\AutomatedReports\AskJiminnyReportActivityServiceTesta fittersemoty when no resultsperiod date filters1de handtes scalyr flttersget activity ids hassees sn zero sequence number to disable first r._ 0.025All 8 tests pass. Here's a summary:Root Cause & FixRoot cause: buildRequestParamsFromSearch never set sequence number in the request params, so Criteria::createFromRequest defaulted it to 0Since isFirstRequest() returns true when sequenceNumber === 0, several implicit defaults were silently applied:Activitvourat ionRande → min duration = 1 ilters ouf o-second activitiesiActivityRecorded → only_recorded = 1 (restricts to recorded activities only)OrganiserGroupIn → applies user's default group as a filterThe frontend URL you noticed uses sequence_number=4, which disables these defaults - explaining why the frontend returned activities but the servicereturee o.Fix: AskJiminnyReportActivityService.php:51—added 'sequence_number' » 1 to the Criteria::createFromRequest merge, ensuring isFirstRequest() returns false and no implicit defaults are injected.lest added: testbetacc1cylasPassesNonzerosequencenumberloDisablerarsckequestberaulus assers that the captured uriteria ob ect nas 1srirstRequest() === false.Öul ..Vew allliItlle wiun changesvapp/Services/Kiosk/AutomatedReports/D AskJiminnyReportActivityService.php +1 -1Reject allAccept allExplain it to me again. Why is there issue with that? Where is it expected and wy do l need to fork with that. How is it used [EMAIL]<>CodeClaude Sonnet 4.6W Windsurf Teams298:48uir-o( 4 spaces...
|
NULL
|
NULL
|
NULL
|
11095
|
|
11094
|
PhpStormFileEditViewNavigateCodeLaravelRefactorFV PhpStormFileEditViewNavigateCodeLaravelRefactorFV faVsco.js v#11894 on JY-18909-automated-reports-ask-liminny k vProject vToolsWindowHelp© JiminnyDebugCommanc©JiminnySetEncryptedTo© JiminnyTokenInfoComn© MakeSlackLivecoaching© Managescim-orleam.p(c Malkoanchrocnvronnl© MuteOrganizerChannel.© PhpApm.php© PropagateCoachingFeer© PurgeConferences.php© PurgeSoftDeletedOppor© PurgeSyncBatchesComiC RecalculateDealRisksCa© RemoveDeleteMarkersC© RemoveExpiredNudgesi© RemoveUnusedParticip:C ResetElasticSearch.php© RestoreActivityCrmProv© RestoreActivityTypeCor© SeedActivities.php© SyncActivity.php©Tracklmported.php© UpdateActivitiesAverag© WhichWorkerlsWorkingr> Scheduling© Kernel.phpM Contracts> M Domain> MDTO> M Emails› _ Enums> D Events> D Exceptions> DJ FFMpeg>D Formats› D Guards› C Helpersv UHttp> MAccessTokenProviderv D ControllersV MAPI> D AiCallScoringAiReports> D Deallnsights> D Opportunity> C Page> • Scorecards> D SettingsTeamInsightsnemes> MUserAutomatedRepov DV2C ACIMINVACOnTOAskAnythingCont© AskJiminnyReporl© DealsV2Controlle:© OnDemandV2Con© PlaylistController.© PlaylistShareContTests passed: 1 (3 minutes ago)© ReportController.php© AutomatedReportsCommand.phpJiminnybeouecommana.ong= custom.log= laravel.logA SF [jiminny@localhost]A HS_local [jiminny@localhost]A console [PROD]< console LUlconsole SlAGiNGAskJIminnykepor Acuivilyservice.ongACuiVilysearch.onp© AutomatedReportsSendCommand.php© AddLayoutEntities.php© Team.php© AutomatedReportsRepository.php X© AutomatedReportsService.phpCrealenelaAcuviyevent.onoOnDemandV2Controller.php© HistoryService.php© FilterDefinitionCollection.php© Criteria.php© AskJiminnyReportActivityServiceTest.phpC) RequestGenerateAskJiminnyReportJobTest.phpclass OnDemandV2Controller extends Controller41 M2 ^(e TrackProvidernstallled-vent.ono241public function askAnything(OnDemandAskAnythingRequest $request): StreamedResponse |JsonResp→ ounouLbala lllessauer© CreateActivityLoggedEvent.php© UserPilotActivityListener.php262'callIds' => $this->historyService->getContextIds($user,identifier: HistoryServic263'history' => $this->historyService->getHistory($user,identifier: HistoryService::• ActivityLogged.phpAutomatedReportsCallbackService.php264C RequestGenerateAskJiminnyReportJob.php265266$teamAiContext = $this->teamAiContextRepository->getByTeamId($user->getTeamId()):RequestGenerateReportJob.php© AutomatedReportResult.phpif ($teamAiContext?->getPrompt() !== null) {(C) AutomatedReport.php268"reouescvaral'teanaucontext' = "reanazcontext->deurronotoclass Automacedкeрortskepo o:A15 X4 Av20961627593114115116117118119121123LI4/**273* Retrieve all standard (non-Ask Jiminny) M274* @param string $sortColumnThe column to276*dparam string ssortulrection ine sort dire277* @return Collection<AutomatedReport>.278279*/12 usagespublic function getAllStandardReports(string $sortColumn = 'created_at',string $sortDirection = 'desc'): Collection {..[PHONE]84285/**286287* Retrieve all Ask Liminny reports created A288* Oodrdll usernusenIne user Ynos* @param string $sortColumnThe column te290* Oparam string $sortDirection The sort dire2911475* @return Collection<AutomatedReport>294*/-29514 usages296public function getAskJiminnyReportsByUser(User $user,298string $sortColumn = 'created_at',string ssorcbirection = "desc"): Collection {...}300301—302Z usagesprivate function buildSortedQuery(string $sor]305504/**—305306* Get all active and enabled reports with ac—307308* @param string $frequency309— 310* dreturh coLcectzon<aucomacedкeрort>31131223 usagespublic function getActiveReportsByFrequency(s)314$this->historyService->appendToUserHistory($user,identifier: HistoryService::0N_DEMAND_SERVICE,$inputData[ 'message']):$this->historyService->appendToEventHistory(user: $user,identifier: HistoryService::0N_DEMAND_SERVICE,type: HistoryService::EVENT_IN_PROGRESS_TYPE):$streamRequest = StreamRequest: :onDemandLevel($requestData);// Track active stream in Redis$this->activeStreamsRepository->start($user->getId(),$streamRequest->getId(),ttlSeconds: $streamRequest->getConnectTimeout() + $streamRequest->getReadTimeot):rerur uns-porooneroeru ce-poerotreanecuraoorteoresconsestreankeovest, "strealikecuest.onCompleted: function (string $assistantResponse,bool $clientAborted,bool $hadError,) use ($user, $streamRequest) {// Remove in-progress eventSthis->historyService->removeLastEventMessageByType($user,identifier: HistoryService: : ON_DEMAND_SERVICE,type: HistorvService::EVENT IN PROGRESS TYPE// Save to history if backend completed successfully (even if client discor// Only skip saving if there was an actual error during streamingif (! $hadError && ! empty(trim($assistantResponse))) {$this->historyService->appendToSystemHistory($user,identifier: HistoryService::0N_DEMAND_SERVICE,$assistantResponse,, 0lablf Support Daily • in 2h 48 mAAskJiminnyReportActivityServiceT…Defaults100% C•Tue 14 Apr 12:12:32CascadeFixing ReportControllerAutomated Report MarFixing Ask Jiminny Rep+D ...Now let's run the test to verifvdesker nte/ sockces/k.osk/AuPowar/orts/artman yeportActivityserviceTest.php --no-coverageloul nor oen Indlr tler var w nunwarusandoster nxe ceockes /kJosk/AuP /ape/a/poras/A5kJ1minyReportActivityServiceTest. php --no-coverageCould not open input file: /app/artisanCommand dockerocker exec oocker land ioash —eSid php artisan testLests unlu services Klosk Aucomaceakeporcs AskJiminnykeportAccivityservicelest.ono =-no-coverade D&l'Could not open input file: artisan• docker exec docker lamp 1 bash -c "find / -name artisan -maxdeoth 6 2>/dev/null | head -5"/home/jiminny/artisaniminny && php artisan testdests/unxe/servaces/K1osk/AusomatedReports/AskJ1maynyReportActivaty5erviceTest-php --no-coverage 2>61"PASSTests\Unit\Services\Kiosk\AutomatedReports\AskJiminnyReportActivityServiceTestreturnsfiltersemoty when no resultsE tatt tnt hperiod date filtersids bassess snazero fsequence number to disable first ._. 0.025All 8 tests pass. Here's a summary:Root Cause & FixKoOL cause: bu1 Ldkequestraramst romsearch never set sequence number In the request params, so criterla::creater romkequest delaulted lt to 0Since isFirstRequest() returns true when sequenceNumber === 0, several implicit defaults were silently applied:Activitvourat ionRande → min duration = 1 ilters ouf o-second activitiesiActivityRecorded → only_recorded = 1 (restricts to recorded activities only)OrganiserGroupIn → applies user's default group as a filtelThe frontend URL you noticed uses sequence_number=4, which disables these defaults - explaining why the frontend returned activities but the servicereturee o.Fix: AskJiminnyReportActivityService.php:51 - added 'sequence_number' = 1 to the Criteria:: createFromRequest merge, ensuring isFirstRequest() returns false and no implicit defaults are injected.sequencenumberloD1sablerirsckequestberauuus asserts that the captured uriteria ob ect nas 1srirsO filesystems.phprlleutiiong• FilterNormalizer.php app/UtilsrleutllestonoFlesvstem-xcention.ohvFileNotFoundException.php app/Exceptions/Fltervormalizerlect.ohnO Filter.phpO FileService.phpReportActivityService.php +1 -1O FilterDefinition.phpExplain it to me again. Why is there issue with that? Where is it expected and wy do I need to fork with that. How is it used in efi y+ <> CodeClaude Sonnet 4.6Öul ..Vew allliReject allAccept allWinasun leams298:48uir-o( 4 spaces...
|
NULL
|
NULL
|
NULL
|
11094
|
|
11093
|
Project: faVsco.js, menu
#11894 on JY-18909-automa Project: faVsco.js, menu
#11894 on JY-18909-automated-reports-ask-jiminny, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceT…Defaults
Run 'AskJiminnyReportActivityServiceTest.tes…uenceNumberToDisableFirstRequestDefaults'
Debug 'AskJiminnyReportActivityServiceTest.tes…uenceNumberToDisableFirstRequestDefaults'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Sync Changes
Hide This Notification
Code changed:
Hide
1
2
Previous Highlighted Error
Next Highlighted Error
<?php
declare(strict_types=1);
namespace Jiminny\Http\Controllers\API\V2;
use Exception;
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Routing\Controller;
use Illuminate\Validation\ValidationException;
use Jiminny\Component\ActivitySearch\Service\ActivitySearch;
use Jiminny\Component\AskAnything\HistoryService;
use Jiminny\Component\AskJiminnyAi\Exceptions\AskJiminnyException;
use Jiminny\Component\AskJiminnyAi\OnDemandLevel\Events\AskAnythingAbortedChatCompleted;
use Jiminny\Component\Prophet\ProphetService;
use Jiminny\Component\ProphetAi\StreamRequest;
use Jiminny\Events\EventDispatcher;
use Jiminny\Exceptions\ActivityProviderException;
use Jiminny\Http\Requests\API\V2\OnDemandAskAnythingRequest;
use Jiminny\Models\Feature\FeatureEnum;
use Jiminny\Models\User;
use Jiminny\Repositories\ActiveStreamsRepository;
use Jiminny\Repositories\ElasticActivityRepository;
use Jiminny\Repositories\TeamAiContextRepository;
use Jiminny\Utils\FilterNormalizer;
use Jiminny\VO;
use Psr\Log\LoggerInterface;
use Symfony\Component\HttpFoundation\Response as ResponseAlias;
use Symfony\Component\HttpFoundation\StreamedResponse;
class OnDemandV2Controller extends Controller
{
use AuthorizesRequests;
private const int DEFAULT_TOP_ACTIVITIES_COUNT = 100;
private const array FILTER_KEY_EXCLUDED_PARAMS = [
'sequence_number',
'page',
'per_page',
'limit',
'offset',
];
public function __construct(
private readonly ActivitySearch $activitySearch,
private readonly HistoryService $historyService,
private readonly ProphetService $prophetService,
private readonly TeamAiContextRepository $teamAiContextRepository,
private readonly ActiveStreamsRepository $activeStreamsRepository,
private readonly EventDispatcher $eventDispatcher,
private readonly LoggerInterface $logger,
) {
}
/**
* Check if the user's team has the ASK_JIMINNY_ON_ANYTHING feature enabled
*/
private function checkAskJiminnyOnAnythingFeature(User $user): ?JsonResponse
{
if (! $user->team->hasFeature(FeatureEnum::ASK_JIMINNY_ON_ANYTHING)) {
return new JsonResponse([
'message' => 'Feature ASK_JIMINNY_ON_ANYTHING is not enabled for this team',
], ResponseAlias::HTTP_FORBIDDEN);
}
return null;
}
/**
* Get top N activity IDs for Ask Jiminny feature based on filters
*
* @throws ValidationException
* @throws ActivityProviderException
*/
public function getContextForAskAnythingByFilter(Request $request, ElasticActivityRepository $repository): JsonResponse
{
/** @var User $user */
$user = $request->user();
if ($featureCheck = $this->checkAskJiminnyOnAnythingFeature($user)) {
return $featureCheck;
}
$topCount = $request->input('top_count', self::DEFAULT_TOP_ACTIVITIES_COUNT);
try {
// Always fetch first N (top count) IDs
$onDemandActivitySearchCriteria = VO\Repository\OnDemandActivitySearch\Criteria::createFromRequest(
array_merge($request->all(), ['limit' => $topCount, 'page' => 1]),
$user->getTimezone()
);
$filterSet = $this->activitySearch->getOnDemandPageFilterSet($onDemandActivitySearchCriteria, $user);
$validationRules = $filterSet->getValidationRules()
->merge([
'exclude' => 'array',
'limit' => 'integer|min:1|max:' . $topCount,
])
->all();
$request->validate($validationRules);
$hasChangedFilters = $this->hasChangedContextFilter($request, $user);
$activityIds = $repository->onDemandSearchIdsOnly($user, $onDemandActivitySearchCriteria, $filterSet);
$this->historyService->storeContextIds($user, HistoryService::CONTEXT_IDS, $activityIds);
return new JsonResponse([
'count' => count($activityIds),
'changed_context_filters' => $hasChangedFilters,
], ResponseAlias::HTTP_OK);
} catch (Exception $e) {
$this->logger->error('Failed to fetch activity IDs for Ask Jiminny', [
'error' => $e->getMessage(),
'user_id' => $user->getId(),
]);
return new JsonResponse([
'ids' => [],
'error' => 'Failed to fetch activity IDs',
], ResponseAlias::HTTP_INTERNAL_SERVER_ERROR);
}
}
private function hasChangedContextFilter(Request $request, User $user): bool
{
$filterKey = $this->makeFilterKey($request);
$result = $this->historyService->compareAndSetFilterKeyWithHistory($user, $filterKey);
if (! $result['changed']) {
return false;
}
if ($result['matches_previous']) {
return false;
}
$history = $this->historyService->getHistory($user, HistoryService::ON_DEMAND_SERVICE);
// If no history or last event already matches, return false
if (empty($history) || $this->historyService->hasFilteredChangedEventAsLastMessage($history)) {
return false;
}
// Append event and notify
$this->historyService->appendToEventHistory(
user: $user,
identifier: HistoryService::ON_DEMAND_SERVICE,
type: HistoryService::EVENT_FILTERS_CHANGED_TYPE
);
return true;
}
private function makeFilterKey(Request $request): string
{
$filters = $request->except(self::FILTER_KEY_EXCLUDED_PARAMS);
try {
$normalizedFilters = FilterNormalizer::normalizeFilters($filters);
$json = json_encode(
$normalizedFilters,
JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE | JSON_THROW_ON_ERROR
);
return hash('xxh3', $json);
} catch (\JsonException $e) {
$this->logger->error('Failed to encode filters', [
'error' => $e->getMessage(),
'filters_keys' => array_keys($filters),
]);
throw new AskJiminnyException('Failed to create filter key', 0, $e);
}
}
/**
* Get Ask Anything conversation history
*/
public function getAskAnythingHistory(Request $request): JsonResponse
{
/** @var User $user */
$user = $request->user();
if ($featureCheck = $this->checkAskJiminnyOnAnythingFeature($user)) {
return $featureCheck;
}
try {
$history = $this->historyService->getHistory($user, HistoryService::ON_DEMAND_SERVICE);
return new JsonResponse($history, ResponseAlias::HTTP_OK);
} catch (Exception $e) {
$this->logger->error('Failed to fetch Ask Anything history', [
'error' => $e->getMessage(),
'user_id' => $user->getId(),
]);
return new JsonResponse([
'history' => [],
'error' => 'Failed to fetch history',
], ResponseAlias::HTTP_INTERNAL_SERVER_ERROR);
}
}
/**
* Delete Ask Anything conversation history
*/
public function deleteAskAnythingHistory(Request $request): JsonResponse
{
/** @var User $user */
$user = $request->user();
if ($featureCheck = $this->checkAskJiminnyOnAnythingFeature($user)) {
return $featureCheck;
}
try {
$this->historyService->deleteHistory($user, HistoryService::ON_DEMAND_SERVICE);
return new JsonResponse([
'message' => 'History deleted successfully',
], ResponseAlias::HTTP_OK);
} catch (Exception $e) {
$this->logger->error('Failed to delete Ask Anything history', [
'error' => $e->getMessage(),
'user_id' => $user->getId(),
]);
return new JsonResponse([
'error' => 'Failed to delete history',
], ResponseAlias::HTTP_INTERNAL_SERVER_ERROR);
}
}
/**
* Ask Anything - submit question and get AI response
*/
public function askAnything(OnDemandAskAnythingRequest $request): StreamedResponse|JsonResponse
{
/** @var User $user */
$user = $request->user();
$this->logger->info('AskAnything request received', [
'user_id' => $user->getId(),
'team_id' => $user->getTeamId(),
'request_hash' => md5($request->input('message') . $user->getId() . floor(time() / 60)),
'message_preview' => mb_substr($request->input('message'), 0, 50),
]);
if ($featureCheck = $this->checkAskJiminnyOnAnythingFeature($user)) {
return $featureCheck;
}
try {
$inputData = $request->validated();
$requestData = [
'userQuestion' => $inputData['message'],
'callIds' => $this->historyService->getContextIds($user, HistoryService::CONTEXT_IDS),
'history' => $this->historyService->getHistory($user, HistoryService::ON_DEMAND_SERVICE),
];
$teamAiContext = $this->teamAiContextRepository->getByTeamId($user->getTeamId());
if ($teamAiContext?->getPrompt() !== null) {
$requestData['teamAiContext'] = $teamAiContext->getPrompt();
}
$this->historyService->appendToUserHistory(
$user,
HistoryService::ON_DEMAND_SERVICE,
$inputData['message']
);
$this->historyService->appendToEventHistory(
user: $user,
identifier: HistoryService::ON_DEMAND_SERVICE,
type: HistoryService::EVENT_IN_PROGRESS_TYPE
);
$streamRequest = StreamRequest::onDemandLevel($requestData);
// Track active stream in Redis
$this->activeStreamsRepository->start(
$user->getId(),
$streamRequest->getId(),
ttlSeconds: $streamRequest->getConnectTimeout() + $streamRequest->getReadTimeout()
);
return $this->prophetService->getStreamedOrAbortedResponse(
streamRequest: $streamRequest,
onCompleted: function (
string $assistantResponse,
bool $clientAborted,
bool $hadError,
) use ($user, $streamRequest) {
// Remove in-progress event
$this->historyService->removeLastEventMessageByType(
$user,
HistoryService::ON_DEMAND_SERVICE,
HistoryService::EVENT_IN_PROGRESS_TYPE
);
// Save to history if backend completed successfully (even if client disconnected)
// Only skip saving if there was an actual error during streaming
if (! $hadError && ! empty(trim($assistantResponse))) {
$this->historyService->appendToSystemHistory(
$user,
HistoryService::ON_DEMAND_SERVICE,
$assistantResponse,
);
}
// Notify frontend if client disconnected (so it can update UI if still on page)
if ($clientAborted) {
$this->eventDispatcher->dispatch(
new AskAnythingAbortedChatCompleted(
user: $user,
identifier: HistoryService::ON_DEMAND_SERVICE,
response: $assistantResponse,
)
);
}
// Remove active stream in Redis
$this->activeStreamsRepository->stop($user->getId(), $streamRequest->getId());
}
);
} catch (Exception $e) {
$this->historyService->removeLastEventMessageByType(
$user,
HistoryService::ON_DEMAND_SERVICE,
HistoryService::EVENT_IN_PROGRESS_TYPE
);
$this->logger->error('Failed to process Ask Anything request', [
'error' => $e->getMessage(),
'user_id' => $user->getId(),
'question' => $request->input('message'),
]);
return new JsonResponse([
'error' => 'Failed to process your question',
], ResponseAlias::HTTP_INTERNAL_SERVER_ERROR);
}
}
public function stopStream(Request $request): JsonResponse
{
$user = $request->user();
$this->activeStreamsRepository->stopByUser($user->getId());
$this->historyService->removeLastEventMessageByType(
$user,
HistoryService::ON_DEMAND_SERVICE,
HistoryService::EVENT_IN_PROGRESS_TYPE
);
return response()->json(['message' => 'Stream marked as stopped by user']);
}
}
Sync Changes
Hide This Notification
Code changed:
Hide
15
4
Previous Highlighted Error
Next Highlighted Error
<?php
declare(strict_types=1);
namespace Jiminny\Repositories;
use Carbon\CarbonImmutable;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Support\Carbon;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Pagination\LengthAwarePaginator;
use Illuminate\Support\Facades\DB;
use Jiminny\Models\AutomatedReport;
use Jiminny\Models\AutomatedReportResult;
use Jiminny\Models\Team;
use Jiminny\Models\User;
use Jiminny\Services\Kiosk\AutomatedReports\AutomatedReportsService;
use Jiminny\Services\Kiosk\AutomatedReports\ReportSort;
use Jiminny\Services\Kiosk\AutomatedReports\ReportSortDirection;
class AutomatedReportsRepository
{
/**
* Create a new automated report
*
* @param array $data
*
* @return AutomatedReport
*/
public function create(array $data): AutomatedReport
{
return AutomatedReport::create($data);
}
/**
* Find an automated report by UUID
*
* @param string $uuid
*
* @return AutomatedReport|null
*/
public function findByUuid(string $uuid): ?AutomatedReport
{
return AutomatedReport::where('uuid', AutomatedReport::toOptimized($uuid))->first();
}
public function findByIdOrUuid(string $idOrUuid): ?AutomatedReport
{
if (is_numeric($idOrUuid)) {
return AutomatedReport::find((int) $idOrUuid);
}
return AutomatedReport::where('uuid', AutomatedReport::toOptimized($idOrUuid))->first();
}
/**
* Retrieve all standard (non-Ask Jiminny) automated reports.
*
* @param string $sortColumn The column to sort by. Allowed values: 'created_by', 'created_at'. Defaults to 'created_at'.
* @param string $sortDirection The sort direction. Allowed values: 'asc', 'desc'. Defaults to 'desc'.
*
* @return Collection<AutomatedReport>
*/
public function getAllStandardReports(
string $sortColumn = 'created_at',
string $sortDirection = 'desc'
): Collection {
return $this->buildSortedQuery($sortColumn, $sortDirection)
->whereNot('type', AutomatedReportsService::TYPE_ASK_JIMINNY)
->get();
}
/**
* Retrieve all Ask Jiminny reports created by the given user.
*
* @param User $user The user whose reports to retrieve.
* @param string $sortColumn The column to sort by. Allowed values: 'created_by', 'created_at'. Defaults to 'created_at'.
* @param string $sortDirection The sort direction. Allowed values: 'asc', 'desc'. Defaults to 'desc'.
*
* @return Collection<AutomatedReport>
*/
public function getAskJiminnyReportsByUser(
User $user,
string $sortColumn = 'created_at',
string $sortDirection = 'desc'
): Collection {
return $this->buildSortedQuery($sortColumn, $sortDirection)
->where('type', AutomatedReportsService::TYPE_ASK_JIMINNY)
->where('created_by', $user->getId())
->get();
}
private function buildSortedQuery(string $sortColumn, string $sortDirection): \Illuminate\Database\Eloquent\Builder
{
$allowedColumns = ['created_by', 'created_at'];
if (! in_array($sortColumn, $allowedColumns)) {
$sortColumn = 'created_at';
}
$sortDirection = strtolower($sortDirection) === 'asc' ? 'asc' : 'desc';
$query = AutomatedReport::query()->with(['creator', 'team']);
if ($sortColumn === 'created_by') {
$query->leftJoin('users', 'users.id', '=', 'automated_reports.created_by')
->orderByRaw("users.name COLLATE utf8mb4_unicode_ci {$sortDirection}")
->select('automated_reports.*');
} else {
$query->orderBy($sortColumn, $sortDirection);
}
return $query;
}
/**
* Get all active and enabled reports with active teams for the specified frequency.
*
* @param string $frequency
*
* @return Collection<AutomatedReport>
*/
public function getActiveReportsByFrequency(string $frequency): Collection
{
return AutomatedReport::where('automated_reports.status', true)
->where('automated_reports.frequency', $frequency)
->join('teams', 'automated_reports.team_id', '=', 'teams.id')
->where('teams.status', Team::STATUS_ACTIVE)
->where(function ($query) {
$query->whereNull('automated_reports.expires_at')
->orWhere('automated_reports.expires_at', '>=', now()->toDateString());
})
->select('automated_reports.*')
->get();
}
/**
* Update an automated report
*
* @param AutomatedReport $report
* @param array $data
*
* @return AutomatedReport
*/
public function update(AutomatedReport $report, array $data): AutomatedReport
{
$report->update($data);
return $report;
}
/**
* Create a new automated report result.
*
* @param array $data The data to create the automated report result with.
*
* @return AutomatedReportResult The newly created automated report result.
*/
public function createResult(array $data): AutomatedReportResult
{
return AutomatedReportResult::create($data);
}
/**
* Find an automated report result by UUID.
*
* @param string $uuid The UUID to find the automated report result with.
*
* @return AutomatedReportResult|null The automated report result if found, otherwise null.
*/
public function findResultByUuid(string $uuid): ?AutomatedReportResult
{
return AutomatedReportResult::where('uuid', AutomatedReportResult::toOptimized($uuid))->first();
}
public function findResultByUuidForUser(string $uuid, User $user): ?AutomatedReportResult
{
return AutomatedReportResult::query()
->where('uuid', AutomatedReportResult::toOptimized($uuid))
->whereHas('report', static function ($query) use ($user): void {
$query->where('team_id', $user->getTeamId())
->where('created_by', $user->getId());
})
->first();
}
public function findChildResult(AutomatedReportResult $result, string $type): ?AutomatedReportResult
{
return AutomatedReportResult::query()
->where('parent_id', $result->getId())
->where('media_type', $type)
->first();
}
public function getGeneratedNotSentResults(): Collection
{
return AutomatedReportResult::query()
->whereNotNull('generated_at')
->whereNull('sent_at')
->where('status', AutomatedReportResult::STATUS_GENERATED)
->whereHas('report')
->with('report')
->get();
}
public function getPaginatedUserReports(
User $user,
ReportSort $sort,
ReportSortDirection $sortDirection,
int $resultsPerPage,
int $page,
?Carbon $fromDate,
?Carbon $toDate,
array $teamIds,
array $reportTypes,
?string $name,
): LengthAwarePaginator {
$query = AutomatedReportResult::query()
->whereNotNull('automated_report_results.generated_at')
->join('automated_reports', 'automated_report_results.report_id', '=', 'automated_reports.id')
->where('automated_reports.team_id', $user->getTeamId())
->whereJsonContains('automated_reports.recipients->users', $user->getId())
->orderByRaw("$sort->value COLLATE utf8mb4_unicode_ci {$sortDirection->value}")
->select('automated_report_results.*')
->with('report.team');
if ($fromDate !== null && $toDate !== null) {
$query->whereBetween('generated_at', [$fromDate, $toDate]);
}
if (! empty($teamIds)) {
$query->where(function ($q) use ($teamIds) {
foreach ($teamIds as $id) {
$q->orWhereJsonContains('automated_reports.groups', $id);
}
});
}
if (! empty($reportTypes)) {
$query->whereIn('automated_reports.type', $reportTypes);
}
if (! empty($name)) {
$query->whereLike('name', "%$name%");
}
return $query->paginate($resultsPerPage, ['*'], 'page', $page);
}
public function countUserReports(User $user): int
{
return AutomatedReportResult::query()
->whereNotNull('generated_at')
->whereNotNull('sent_at')
->whereHas('report', function ($q) use ($user) {
$q->where('team_id', $user->getTeamId())
->whereJsonContains('recipients->users', $user->getId());
})
->count();
}
/**
* Get report IDs for a specific team
*
* @param Team $team
*
* @return \Illuminate\Support\Collection
*/
public function getReportIdsByTeam(Team $team): \Illuminate\Support\Collection
{
return AutomatedReport::where('team_id', $team->getId())->pluck('id');
}
/**
* Get all reports for a specific team
*
* @param Team $team
*
* @return Collection
*/
public function getReportsByTeam(Team $team): Collection
{
return AutomatedReport::where('team_id', $team->getId())->get();
}
/**
* Get all report results for a specific report
*
* @param AutomatedReport $report
*
* @return Collection
*/
public function getResultsByReport(AutomatedReport $report): Collection
{
return $this->getResultsByReportQuery($report)->get();
}
public function getResultsByReportQuery(AutomatedReport $report): Builder
{
return AutomatedReportResult::where('report_id', $report->getId());
}
public function getReportResultsQueryForRetention(Team $team, CarbonImmutable $retentionDate): Builder
{
$reportIds = $this->getReportIdsByTeam($team);
return AutomatedReportResult::query()->whereIn('report_id', $reportIds)
->whereRaw('IFNULL(generated_at, created_at) <= ?', [$retentionDate]);
}
/**
* @param int|null $teamId Optional team ID to filter results
*
* @return \Illuminate\Support\Collection<int, int> Collection of team IDs
*/
public function getTeamIdsWithReportsResults(?int $teamId = null): \Illuminate\Support\Collection
{
$query = DB::table('automated_reports')
->join('teams', 'automated_reports.team_id', '=', 'teams.id')
->select('teams.id')
->distinct();
if ($teamId !== null) {
$query->where('teams.id', $teamId);
}
return $query->pluck('teams.id');
}
}
Project
Project
New File or Directory…
Expand Selected
Collapse All
Options
Hide...
|
PhpStorm
|
faVsco.js – OnDemandV2Controller.php
|
NULL
|
11093
|
|
11092
|
Project: faVsco.js, menu
#11894 on JY-18909-automa Project: faVsco.js, menu
#11894 on JY-18909-automated-reports-ask-jiminny, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceT…Defaults
Run 'AskJiminnyReportActivityServiceTest.tes…uenceNumberToDisableFirstRequestDefaults'
Debug 'AskJiminnyReportActivityServiceTest.tes…uenceNumberToDisableFirstRequestDefaults'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Sync Changes
Hide This Notification
Code changed:
Hide
1
2
Previous Highlighted Error
Next Highlighted Error
<?php
declare(strict_types=1);
namespace Jiminny\Http\Controllers\API\V2;
use Exception;
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Routing\Controller;
use Illuminate\Validation\ValidationException;
use Jiminny\Component\ActivitySearch\Service\ActivitySearch;
use Jiminny\Component\AskAnything\HistoryService;
use Jiminny\Component\AskJiminnyAi\Exceptions\AskJiminnyException;
use Jiminny\Component\AskJiminnyAi\OnDemandLevel\Events\AskAnythingAbortedChatCompleted;
use Jiminny\Component\Prophet\ProphetService;
use Jiminny\Component\ProphetAi\StreamRequest;
use Jiminny\Events\EventDispatcher;
use Jiminny\Exceptions\ActivityProviderException;
use Jiminny\Http\Requests\API\V2\OnDemandAskAnythingRequest;
use Jiminny\Models\Feature\FeatureEnum;
use Jiminny\Models\User;
use Jiminny\Repositories\ActiveStreamsRepository;
use Jiminny\Repositories\ElasticActivityRepository;
use Jiminny\Repositories\TeamAiContextRepository;
use Jiminny\Utils\FilterNormalizer;
use Jiminny\VO;
use Psr\Log\LoggerInterface;
use Symfony\Component\HttpFoundation\Response as ResponseAlias;
use Symfony\Component\HttpFoundation\StreamedResponse;
class OnDemandV2Controller extends Controller
{
use AuthorizesRequests;
private const int DEFAULT_TOP_ACTIVITIES_COUNT = 100;
private const array FILTER_KEY_EXCLUDED_PARAMS = [
'sequence_number',
'page',
'per_page',
'limit',
'offset',
];
public function __construct(
private readonly ActivitySearch $activitySearch,
private readonly HistoryService $historyService,
private readonly ProphetService $prophetService,
private readonly TeamAiContextRepository $teamAiContextRepository,
private readonly ActiveStreamsRepository $activeStreamsRepository,
private readonly EventDispatcher $eventDispatcher,
private readonly LoggerInterface $logger,
) {
}
/**
* Check if the user's team has the ASK_JIMINNY_ON_ANYTHING feature enabled
*/
private function checkAskJiminnyOnAnythingFeature(User $user): ?JsonResponse
{
if (! $user->team->hasFeature(FeatureEnum::ASK_JIMINNY_ON_ANYTHING)) {
return new JsonResponse([
'message' => 'Feature ASK_JIMINNY_ON_ANYTHING is not enabled for this team',
], ResponseAlias::HTTP_FORBIDDEN);
}
return null;
}
/**
* Get top N activity IDs for Ask Jiminny feature based on filters
*
* @throws ValidationException
* @throws ActivityProviderException
*/
public function getContextForAskAnythingByFilter(Request $request, ElasticActivityRepository $repository): JsonResponse
{
/** @var User $user */
$user = $request->user();
if ($featureCheck = $this->checkAskJiminnyOnAnythingFeature($user)) {
return $featureCheck;
}
$topCount = $request->input('top_count', self::DEFAULT_TOP_ACTIVITIES_COUNT);
try {
// Always fetch first N (top count) IDs
$onDemandActivitySearchCriteria = VO\Repository\OnDemandActivitySearch\Criteria::createFromRequest(
array_merge($request->all(), ['limit' => $topCount, 'page' => 1]),
$user->getTimezone()
);
$filterSet = $this->activitySearch->getOnDemandPageFilterSet($onDemandActivitySearchCriteria, $user);
$validationRules = $filterSet->getValidationRules()
->merge([
'exclude' => 'array',
'limit' => 'integer|min:1|max:' . $topCount,
])
->all();
$request->validate($validationRules);
$hasChangedFilters = $this->hasChangedContextFilter($request, $user);
$activityIds = $repository->onDemandSearchIdsOnly($user, $onDemandActivitySearchCriteria, $filterSet);
$this->historyService->storeContextIds($user, HistoryService::CONTEXT_IDS, $activityIds);
return new JsonResponse([
'count' => count($activityIds),
'changed_context_filters' => $hasChangedFilters,
], ResponseAlias::HTTP_OK);
} catch (Exception $e) {
$this->logger->error('Failed to fetch activity IDs for Ask Jiminny', [
'error' => $e->getMessage(),
'user_id' => $user->getId(),
]);
return new JsonResponse([
'ids' => [],
'error' => 'Failed to fetch activity IDs',
], ResponseAlias::HTTP_INTERNAL_SERVER_ERROR);
}
}
private function hasChangedContextFilter(Request $request, User $user): bool
{
$filterKey = $this->makeFilterKey($request);
$result = $this->historyService->compareAndSetFilterKeyWithHistory($user, $filterKey);
if (! $result['changed']) {
return false;
}
if ($result['matches_previous']) {
return false;
}
$history = $this->historyService->getHistory($user, HistoryService::ON_DEMAND_SERVICE);
// If no history or last event already matches, return false
if (empty($history) || $this->historyService->hasFilteredChangedEventAsLastMessage($history)) {
return false;
}
// Append event and notify
$this->historyService->appendToEventHistory(
user: $user,
identifier: HistoryService::ON_DEMAND_SERVICE,
type: HistoryService::EVENT_FILTERS_CHANGED_TYPE
);
return true;
}
private function makeFilterKey(Request $request): string
{
$filters = $request->except(self::FILTER_KEY_EXCLUDED_PARAMS);
try {
$normalizedFilters = FilterNormalizer::normalizeFilters($filters);
$json = json_encode(
$normalizedFilters,
JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE | JSON_THROW_ON_ERROR
);
return hash('xxh3', $json);
} catch (\JsonException $e) {
$this->logger->error('Failed to encode filters', [
'error' => $e->getMessage(),
'filters_keys' => array_keys($filters),
]);
throw new AskJiminnyException('Failed to create filter key', 0, $e);
}
}
/**
* Get Ask Anything conversation history
*/
public function getAskAnythingHistory(Request $request): JsonResponse
{
/** @var User $user */
$user = $request->user();
if ($featureCheck = $this->checkAskJiminnyOnAnythingFeature($user)) {
return $featureCheck;
}
try {
$history = $this->historyService->getHistory($user, HistoryService::ON_DEMAND_SERVICE);
return new JsonResponse($history, ResponseAlias::HTTP_OK);
} catch (Exception $e) {
$this->logger->error('Failed to fetch Ask Anything history', [
'error' => $e->getMessage(),
'user_id' => $user->getId(),
]);
return new JsonResponse([
'history' => [],
'error' => 'Failed to fetch history',
], ResponseAlias::HTTP_INTERNAL_SERVER_ERROR);
}
}
/**
* Delete Ask Anything conversation history
*/
public function deleteAskAnythingHistory(Request $request): JsonResponse
{
/** @var User $user */
$user = $request->user();
if ($featureCheck = $this->checkAskJiminnyOnAnythingFeature($user)) {
return $featureCheck;
}
try {
$this->historyService->deleteHistory($user, HistoryService::ON_DEMAND_SERVICE);
return new JsonResponse([
'message' => 'History deleted successfully',
], ResponseAlias::HTTP_OK);
} catch (Exception $e) {
$this->logger->error('Failed to delete Ask Anything history', [
'error' => $e->getMessage(),
'user_id' => $user->getId(),
]);
return new JsonResponse([
'error' => 'Failed to delete history',
], ResponseAlias::HTTP_INTERNAL_SERVER_ERROR);
}
}
/**
* Ask Anything - submit question and get AI response
*/
public function askAnything(OnDemandAskAnythingRequest $request): StreamedResponse|JsonResponse
{
/** @var User $user */
$user = $request->user();
$this->logger->info('AskAnything request received', [
'user_id' => $user->getId(),
'team_id' => $user->getTeamId(),
'request_hash' => md5($request->input('message') . $user->getId() . floor(time() / 60)),
'message_preview' => mb_substr($request->input('message'), 0, 50),
]);
if ($featureCheck = $this->checkAskJiminnyOnAnythingFeature($user)) {
return $featureCheck;
}
try {
$inputData = $request->validated();
$requestData = [
'userQuestion' => $inputData['message'],
'callIds' => $this->historyService->getContextIds($user, HistoryService::CONTEXT_IDS),
'history' => $this->historyService->getHistory($user, HistoryService::ON_DEMAND_SERVICE),
];
$teamAiContext = $this->teamAiContextRepository->getByTeamId($user->getTeamId());
if ($teamAiContext?->getPrompt() !== null) {
$requestData['teamAiContext'] = $teamAiContext->getPrompt();
}
$this->historyService->appendToUserHistory(
$user,
HistoryService::ON_DEMAND_SERVICE,
$inputData['message']
);
$this->historyService->appendToEventHistory(
user: $user,
identifier: HistoryService::ON_DEMAND_SERVICE,
type: HistoryService::EVENT_IN_PROGRESS_TYPE
);
$streamRequest = StreamRequest::onDemandLevel($requestData);
// Track active stream in Redis
$this->activeStreamsRepository->start(
$user->getId(),
$streamRequest->getId(),
ttlSeconds: $streamRequest->getConnectTimeout() + $streamRequest->getReadTimeout()
);
return $this->prophetService->getStreamedOrAbortedResponse(
streamRequest: $streamRequest,
onCompleted: function (
string $assistantResponse,
bool $clientAborted,
bool $hadError,
) use ($user, $streamRequest) {
// Remove in-progress event
$this->historyService->removeLastEventMessageByType(
$user,
HistoryService::ON_DEMAND_SERVICE,
HistoryService::EVENT_IN_PROGRESS_TYPE
);
// Save to history if backend completed successfully (even if client disconnected)
// Only skip saving if there was an actual error during streaming
if (! $hadError && ! empty(trim($assistantResponse))) {
$this->historyService->appendToSystemHistory(
$user,
HistoryService::ON_DEMAND_SERVICE,
$assistantResponse,
);
}
// Notify frontend if client disconnected (so it can update UI if still on page)
if ($clientAborted) {
$this->eventDispatcher->dispatch(
new AskAnythingAbortedChatCompleted(
user: $user,
identifier: HistoryService::ON_DEMAND_SERVICE,
response: $assistantResponse,
)
);
}
// Remove active stream in Redis
$this->activeStreamsRepository->stop($user->getId(), $streamRequest->getId());
}
);
} catch (Exception $e) {
$this->historyService->removeLastEventMessageByType(
$user,
HistoryService::ON_DEMAND_SERVICE,
HistoryService::EVENT_IN_PROGRESS_TYPE
);
$this->logger->error('Failed to process Ask Anything request', [
'error' => $e->getMessage(),
'user_id' => $user->getId(),
'question' => $request->input('message'),
]);
return new JsonResponse([
'error' => 'Failed to process your question',
], ResponseAlias::HTTP_INTERNAL_SERVER_ERROR);
}
}
public function stopStream(Request $request): JsonResponse
{
$user = $request->user();
$this->activeStreamsRepository->stopByUser($user->getId());
$this->historyService->removeLastEventMessageByType(
$user,
HistoryService::ON_DEMAND_SERVICE,
HistoryService::EVENT_IN_PROGRESS_TYPE
);
return response()->json(['message' => 'Stream marked as stopped by user']);
}
}
Sync Changes
Hide This Notification
Code changed:
Hide
15
4
Previous Highlighted Error
Next Highlighted Error
<?php
declare(strict_types=1);
namespace Jiminny\Repositories;
use Carbon\CarbonImmutable;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Support\Carbon;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Pagination\LengthAwarePaginator;
use Illuminate\Support\Facades\DB;
use Jiminny\Models\AutomatedReport;
use Jiminny\Models\AutomatedReportResult;
use Jiminny\Models\Team;
use Jiminny\Models\User;
use Jiminny\Services\Kiosk\AutomatedReports\AutomatedReportsService;
use Jiminny\Services\Kiosk\AutomatedReports\ReportSort;
use Jiminny\Services\Kiosk\AutomatedReports\ReportSortDirection;
class AutomatedReportsRepository
{
/**
* Create a new automated report
*
* @param array $data
*
* @return AutomatedReport
*/
public function create(array $data): AutomatedReport
{
return AutomatedReport::create($data);
}
/**
* Find an automated report by UUID
*
* @param string $uuid
*
* @return AutomatedReport|null
*/
public function findByUuid(string $uuid): ?AutomatedReport
{
return AutomatedReport::where('uuid', AutomatedReport::toOptimized($uuid))->first();
}
public function findByIdOrUuid(string $idOrUuid): ?AutomatedReport
{
if (is_numeric($idOrUuid)) {
return AutomatedReport::find((int) $idOrUuid);
}
return AutomatedReport::where('uuid', AutomatedReport::toOptimized($idOrUuid))->first();
}
/**
* Retrieve all standard (non-Ask Jiminny) automated reports.
*
* @param string $sortColumn The column to sort by. Allowed values: 'created_by', 'created_at'. Defaults to 'created_at'.
* @param string $sortDirection The sort direction. Allowed values: 'asc', 'desc'. Defaults to 'desc'.
*
* @return Collection<AutomatedReport>
*/
public function getAllStandardReports(
string $sortColumn = 'created_at',
string $sortDirection = 'desc'
): Collection {
return $this->buildSortedQuery($sortColumn, $sortDirection)
->whereNot('type', AutomatedReportsService::TYPE_ASK_JIMINNY)
->get();
}
/**
* Retrieve all Ask Jiminny reports created by the given user.
*
* @param User $user The user whose reports to retrieve.
* @param string $sortColumn The column to sort by. Allowed values: 'created_by', 'created_at'. Defaults to 'created_at'.
* @param string $sortDirection The sort direction. Allowed values: 'asc', 'desc'. Defaults to 'desc'.
*
* @return Collection<AutomatedReport>
*/
public function getAskJiminnyReportsByUser(
User $user,
string $sortColumn = 'created_at',
string $sortDirection = 'desc'
): Collection {
return $this->buildSortedQuery($sortColumn, $sortDirection)
->where('type', AutomatedReportsService::TYPE_ASK_JIMINNY)
->where('created_by', $user->getId())
->get();
}
private function buildSortedQuery(string $sortColumn, string $sortDirection): \Illuminate\Database\Eloquent\Builder
{
$allowedColumns = ['created_by', 'created_at'];
if (! in_array($sortColumn, $allowedColumns)) {
$sortColumn = 'created_at';
}
$sortDirection = strtolower($sortDirection) === 'asc' ? 'asc' : 'desc';
$query = AutomatedReport::query()->with(['creator', 'team']);
if ($sortColumn === 'created_by') {
$query->leftJoin('users', 'users.id', '=', 'automated_reports.created_by')
->orderByRaw("users.name COLLATE utf8mb4_unicode_ci {$sortDirection}")
->select('automated_reports.*');
} else {
$query->orderBy($sortColumn, $sortDirection);
}
return $query;
}
/**
* Get all active and enabled reports with active teams for the specified frequency.
*
* @param string $frequency
*
* @return Collection<AutomatedReport>
*/
public function getActiveReportsByFrequency(string $frequency): Collection
{
return AutomatedReport::where('automated_reports.status', true)
->where('automated_reports.frequency', $frequency)
->join('teams', 'automated_reports.team_id', '=', 'teams.id')
->where('teams.status', Team::STATUS_ACTIVE)
->where(function ($query) {
$query->whereNull('automated_reports.expires_at')
->orWhere('automated_reports.expires_at', '>=', now()->toDateString());
})
->select('automated_reports.*')
->get();
}
/**
* Update an automated report
*
* @param AutomatedReport $report
* @param array $data
*
* @return AutomatedReport
*/
public function update(AutomatedReport $report, array $data): AutomatedReport
{
$report->update($data);
return $report;
}
/**
* Create a new automated report result.
*
* @param array $data The data to create the automated report result with.
*
* @return AutomatedReportResult The newly created automated report result.
*/
public function createResult(array $data): AutomatedReportResult
{
return AutomatedReportResult::create($data);
}
/**
* Find an automated report result by UUID.
*
* @param string $uuid The UUID to find the automated report result with.
*
* @return AutomatedReportResult|null The automated report result if found, otherwise null.
*/
public function findResultByUuid(string $uuid): ?AutomatedReportResult
{
return AutomatedReportResult::where('uuid', AutomatedReportResult::toOptimized($uuid))->first();
}
public function findResultByUuidForUser(string $uuid, User $user): ?AutomatedReportResult
{
return AutomatedReportResult::query()
->where('uuid', AutomatedReportResult::toOptimized($uuid))
->whereHas('report', static function ($query) use ($user): void {
$query->where('team_id', $user->getTeamId())
->where('created_by', $user->getId());
})
->first();
}
public function findChildResult(AutomatedReportResult $result, string $type): ?AutomatedReportResult
{
return AutomatedReportResult::query()
->where('parent_id', $result->getId())
->where('media_type', $type)
->first();
}
public function getGeneratedNotSentResults(): Collection
{
return AutomatedReportResult::query()
->whereNotNull('generated_at')
->whereNull('sent_at')
->where('status', AutomatedReportResult::STATUS_GENERATED)
->whereHas('report')
->with('report')
->get();
}
public function getPaginatedUserReports(
User $user,
ReportSort $sort,
ReportSortDirection $sortDirection,
int $resultsPerPage,
int $page,
?Carbon $fromDate,
?Carbon $toDate,
array $teamIds,
array $reportTypes,
?string $name,
): LengthAwarePaginator {
$query = AutomatedReportResult::query()
->whereNotNull('automated_report_results.generated_at')
->join('automated_reports', 'automated_report_results.report_id', '=', 'automated_reports.id')
->where('automated_reports.team_id', $user->getTeamId())
->whereJsonContains('automated_reports.recipients->users', $user->getId())
->orderByRaw("$sort->value COLLATE utf8mb4_unicode_ci {$sortDirection->value}")
->select('automated_report_results.*')
->with('report.team');
if ($fromDate !== null && $toDate !== null) {
$query->whereBetween('generated_at', [$fromDate, $toDate]);
}
if (! empty($teamIds)) {
$query->where(function ($q) use ($teamIds) {
foreach ($teamIds as $id) {
$q->orWhereJsonContains('automated_reports.groups', $id);
}
});
}
if (! empty($reportTypes)) {
$query->whereIn('automated_reports.type', $reportTypes);
}
if (! empty($name)) {
$query->whereLike('name', "%$name%");
}
return $query->paginate($resultsPerPage, ['*'], 'page', $page);
}
public function countUserReports(User $user): int
{
return AutomatedReportResult::query()
->whereNotNull('generated_at')
->whereNotNull('sent_at')
->whereHas('report', function ($q) use ($user) {
$q->where('team_id', $user->getTeamId())
->whereJsonContains('recipients->users', $user->getId());
})
->count();
}
/**
* Get report IDs for a specific team
*
* @param Team $team
*
* @return \Illuminate\Support\Collection
*/
public function getReportIdsByTeam(Team $team): \Illuminate\Support\Collection
{
return AutomatedReport::where('team_id', $team->getId())->pluck('id');
}
/**
* Get all reports for a specific team
*
* @param Team $team
*
* @return Collection
*/
public function getReportsByTeam(Team $team): Collection
{
return AutomatedReport::where('team_id', $team->getId())->get();
}
/**
* Get all report results for a specific report
*
* @param AutomatedReport $report
*
* @return Collection
*/
public function getResultsByReport(AutomatedReport $report): Collection
{
return $this->getResultsByReportQuery($report)->get();
}
public function getResultsByReportQuery(AutomatedReport $report): Builder
{
return AutomatedReportResult::where('report_id', $report->getId());
}
public function getReportResultsQueryForRetention(Team $team, CarbonImmutable $retentionDate): Builder
{
$reportIds = $this->getReportIdsByTeam($team);
return AutomatedReportResult::query()->whereIn('report_id', $reportIds)
->whereRaw('IFNULL(generated_at, created_at) <= ?', [$retentionDate]);
}
/**
* @param int|null $teamId Optional team ID to filter results
*
* @return \Illuminate\Support\Collection<int, int> Collection of team IDs
*/
public function getTeamIdsWithReportsResults(?int $teamId = null): \Illuminate\Support\Collection
{
$query = DB::table('automated_reports')
->join('teams', 'automated_reports.team_id', '=', 'teams.id')
->select('teams.id')
->distinct();
if ($teamId !== null) {
$query->where('teams.id', $teamId);
}
return $query->pluck('teams.id');
}
}
Project
Project
New File or Directory…
Expand Selected
Collapse All
Options
Hide...
|
PhpStorm
|
faVsco.js – OnDemandV2Controller.php
|
NULL
|
11092
|
|
11091
|
+SlackEDHomeDMSActivityFilesLater..•More+FileEditV +SlackEDHomeDMSActivityFilesLater..•More+FileEditViewGoHistoryWindowHelpJiminny ...# Starredplatform-inner-teamChannels# ai-chapter# alerts# backend# confusion-clinic# curiosity_lab# engineering# frontend# general# infra-changes# jiminny-bg# platform-tickets# product launches# random# releases# sofia-office# support# thank-yous# the_people_of jimi…..Direct messagesAneliya Angelova, ...Steliyan GeorgievAdelina Petrova, Ili.... Adelina PetrovaO. Calea Dimitravo→Search Jiminny IncAneliya Angelova, Nikolay Yankov, Steliyan GeorgievMessagesAdd canvas+Nikolay Yankov 10:45 AMпиши кат оя рьннешLukas Kovalik 10:52 AMзабавих се че ми се разбазикаха settings за средипуснах и мина и fail-наима result но e failedзначиREASON_NOT_ENOUGH_ACTIVITIESвиж дали има нещо в OD със този филтьрNikolay Yankov 11:01 AMДобреNikolay Yankov 11:39 AMя рьнни пак LukasLukas Kovalik 11:43 AMготовосьщотоCompetitive pitches беше втория нали такаNikolay Yankov 12:04 PMДа, там има 14 активитита, защо не сработи този пьт?Lukas Kovalik 12:05 PMпак изглежда sequenceгледам гоMessage Aneliya Angelova, Nikolay Yankov, Steliyan Georgiev+Aalal]Support Daily - in 2h 48 m100% <47Tue 14 Apr 12:12:188Today ~...
|
NULL
|
NULL
|
NULL
|
11091
|
|
11090
|
PhpStormFileFV faVsco.js vProject vEditViewNavigat PhpStormFileFV faVsco.js vProject vEditViewNavigateCodeLaravelRefactor#11894 on JY-18909-automated-reports-ask-iminny K vToolsWindowHelp© JiminnyDebugCommanc©JiminnySetEncryptedTo© JiminnyTokenInfoComm© MakeSlackLivecoaching© Managescim-orleam.p(c Malkoanchrorenvironn© MuteOrganizerChannel.© PhpApm.php© PropagateCoachingFeer© PurgeConferences.php© PurgeSoftDeletedOppor© PurgeSyncBatchesComi© RecalculateDealRisksCa© RemoveDeleteMarkersC© RemoveExpiredNudgesi© RemoveUnusedParticip:© ResetElasticSearch.php© RestoreActivityCrmProv© RestoreActivityTypeCor© SeedActivities.php© SyncActivity.php©Tracklmported.php© UpdateActivitiesAverag© WhichWorkerlsWorkingr>D Scheduling© Kernel.phpM Contracts> M Domain> MDTO> M Emails› _ Enums> D Events> D Exceptions> DJ FFMpeg>D Formats› D Guards> D Helpersv UHttp> MAccessTokenProviderv D ControllersV DAPI> DAiCallScoringAiReports> D Deallnsights> D Opportunity> C Page> • ScorecardsSettingsTeamInsightsnemes> MUserAutomatedRepov DV2C ACIMINVACOnTOAskAnythingCont© AskJiminnyReporl© DealsV2Controlle:© OnDemandV2Con© PlaylistController.© PlaylistShareCont© ReportController.php© AutomatedReportsCommand.phpJiminnybeouecommana.ong= custom.log< console EUi= laravel.logA SF [jiminny@localhost]A HS_local [jiminny@localhost]A console [PROD]console SlAGiNG© AskJiminnyReportActivityService.phpACuiVilysearch.onp© AutomatedReportsSendCommand.php© AddLayoutEntities.php© Team.php© AutomatedReportsRepository.php X© AutomatedReportsService.phpCrealenelaAcuviyevent.onoOnDemandV2Controller.php© HistoryService.php© FilterDefinitionCollection.php© Criteria.php© AskJiminnyReportActivityServiceTest.phpC) RequestGenerateAskJiminnyReportJobTest.phpclass OnDemandV2Controller extends ControllerA1 X2 л241public function askAnything(OnDemandAskAnythingRequest $request): StreamedResponse |JsonResp(e) TrackProvidernstallled-vent.ono© CreateActivityLoggedEvent.php© UserPilotActivityListener.php• ActivityLogged.phpAutomatedReportsCallbackService.phpC RequestGenerateAskJiminnyReportJob.phpRequestGenerateReportJob.php© AutomatedReportResult.php(C) AutomatedReport.php260261262263264265266class Automacedкeрortskepo o:A15 M4 . V267268264/**270* Retrieve all standard (non-Ask Liminny) M 271214* @param string $sortColumnThe column t( 273* oparam string esortbirection ine sort dire 274616275931141151161171181191211124123* @return Collection<AutomatedReport>276*/12 usagespublic function getAllStandardReports(string $sortColumn = 'created_at',string $sortDirection = 'desc'): Collection {..[PHONE]81282/**283* Retrieve all Ask Liminny reports created {285286* Oodrdll usernusenThe User Who: 287* @param string $sortColumnThe column tC 288* Oparam string $sortDirection The sort dire 289* @return Collection<AutomatedReport>29029'1*/— 29%14 usages293public function getAskJiminnyReportsByUser(User $user,—2742Y3string $sortColumn = 'created_at',string ssorcbirection = "desc"): Collection {...J2972983302 usagesprivate function buildSortedQuery(string $sor 332-333/**334* Get all active and enabled reports with al 335* @param string $frequency337-338* dreturh coLcectzon<aucomacedкeрort>33934023 usages341public function getActiveReportsByFrequency(§342$requestData = ['userQuestion" => SinputData'message'].'callIds' => $this->historyService->getContextIds($user,loemunel. nascor yocivie'history' => $this->historyService->getHistory($user,identifier: HistoryService::1:$teamAiContext = $this->teamAiContextRepository->getByTeamId($user->getTeamId());if ($teamAiContext?->getPrompt() !== null) {$requestData['teamAiContext'] = $teamAiContext->getPromptO);Sthis->historyService->appendToUserHistorvdsuser,identifier: HistoryService::0N_DEMAND_SERVICE,$inputData[ 'message']):$this->historyService->appendToEventHistory(user: $user,identifier: HistoryService::0N_DEMAND_SERVICE,type: H1scoryservice..EVENI_IN_PRUGRESS_TYPE):$streamRequest = StreamRequest: :onDemandLevel($requestData):// Track active stream in Redis$this->activeStreamsRepository->start($user->getId(),$streamRequest->getId(),ttlSeconds: $streamRequest->getConnectTimeout() + $streamRequest->getReadTimeolreturn $this->prophetService->getStreamed0rAbortedResponse(screankeuest. screankeouest.onCompleted: functionstring $assist &tResponse,bool $clientAborted,bool $hadError,) use ($user, $streamRequest) {...}):} catch (Exception $e) {$this->historyService->removeLastEventMessageByType($user,identher: Historyservice::UN_UENAND_SERVICElype:Hstorvservce...vaM u PRUGkeoswre$this->logger->error('Failed to process Ask Anything request', ['error' => $e->getMessage(),'user_id' => $user-›getId(),'question' => $request->input( key: 'message'),Tests passed: 1 (3 minutes ago), 0lablf Support Daily • in 2h 48 mAAskJiminnyReportActivityServiceT…Defaults100% C•Tue 14 Apr 12:12:17CascadeFixing ReportControllerAutomated Report MarFixing Ask Jiminny Rep+D..Now let's run the test to verifvwtests/Unxt/Servsces/Kiosk/Automate/meports/AskJ1minnyreportActivätyserviceTest-php --no-coveragelou nor oen nolr tler var w nunwarusanCommand dockerdoster nxe ceockes /kJosk/AuP /ape/a/poras/A5kJ1minyReportActivityServiceTest.php --no-coverageCould not open input file: /app/artisanCommand dockeroocker exec oocker lano oasn —c"cd /var/www&& php artisan testLests unlu services Klosk Aucomaceakeporcs AskJiminnykeportAccivityservicelest.ono =-no-coverade D&l'Could not open input file: artisan• docker exec docker_lamp_1 bash -c "find / -name artisan -maxdepth 6 2>/dev/null | head -5"/home/jiminny/artisan"cd /homee/jiminny && php artisan testtests/nxe erckee/Kio5/AutonateReports/5KJimamyReportActivaty ServiceTest, php --no-coverage 2561"PASSTests\Unit\Services\Kiosk\AutomatedReports\AskJiminnyReportActivityServiceTestemoty when no resultsE tatt tnt hperiod date filtershand lesids bassess snazero fsequence number to disable first ._. 0.025All 8 tests pass. Here's a summary:Root Cause & FixRoot cause: buildRequestParamsFromSearch never set sequence number in the request params, so Criteria::createFromRequest defaulted it to 0Since isFirstRequest() returns true when sequenceNumber === 0, several implicit defaults were silently applied:Activitvourat ionRande → min duration = 1 ilters ouf o-second activitiesiActivityRecorded → only_recorded = 1 (restricts to recorded activities only)OrganiserGroupin → apolies user's derault croup as a tiltelThe frontend URL you noticed uses sequence_number=4, which disables these defaults - explaining why the frontend returned activities but the serviceretumee uFix: AskJiminnyReportActivityService.php:51—added 'sequence_number' → 1 to the Criteria::createFromRequest merge, ensuring isFirstRequest() returns false and no implicit defaults are injected.lest added: testbetActLeylasPassesNonzerosequencenumberloD1sablerirsckequestberauuus asserts that the captured uriteria ob ect nas 1srirstRequest() === false.Öul ..Vew allliItlle wiun changesvapp/Services/Kiosk/AutomatedReports/D AskJiminnyReportActivityService.php +1 -1Reject allAccept allExplain it to me again. Why is there issue with that? Where is it expected and wy do l need to fork with that. How is it used in+ <> CodeClaude Sonnet 4.6Winasun leams292:0/uir-o( 4 spaces...
|
NULL
|
NULL
|
NULL
|
11090
|
|
11089
|
+SlackEDHomeDMSActivityFilesLater..•More+FileEditV +SlackEDHomeDMSActivityFilesLater..•More+FileEditViewGoHistoryWindowHelpJiminny ...# Starredplatform-inner-teamChannels# ai-chapter# alerts# backend# confusion-clinic# curiosity_lab# engineering# frontend# general# infra-changes# jiminny-bg# platform-tickets# product_launches# random# releases# sofia-office# support# thank-yous# the_people_of jimi…..Direct messagesAneliya Angelova, ...Steliyan GeorgievAdelina Petrova, Ili.... Adelina PetrovaO. Calea Dimitravo→Search Jiminny IncAneliya Angelova, Nikolay Yankov, Steliyan GeorgievMessagesAdd canvas+Nikolay Yankov 10:45 AMпиши кат оя рьннешLukas Kovalik 10:52 AMзабавих се че ми се разбазикаха settings за средипуснах и мина и fail-наима result но e failedзначиREASON_NOT_ENOUGH_ACTIVITIESвиж дали има нещо в OD със този филтьрNikolay Yankov 11:01 AMДобреNikolay Yankov 11:39 AMя рьнни пак LukasLukas Kovalik 11:43 AMготовосьщотоCompetitive pitches беше втория нали такаNikolay Yankov 12:04 PMДа, там има 14 активитита, защо не сработи този пьт?Lukas Kovalik 12:05 PMпак изглежда sequenceгледам гоMessage Aneliya Angelova, Nikolay Yankov, Steliyan Georgiev+Aalal]Support Daily - in 2h 48 m100% <47Tue 14 Apr 12:12:178Today ~...
|
NULL
|
NULL
|
NULL
|
11089
|
|
11088
|
Project: faVsco.js, menu
#11894 on JY-18909-automa Project: faVsco.js, menu
#11894 on JY-18909-automated-reports-ask-jiminny, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceT…Defaults
Run 'AskJiminnyReportActivityServiceTest.tes…uenceNumberToDisableFirstRequestDefaults'
Debug 'AskJiminnyReportActivityServiceTest.tes…uenceNumberToDisableFirstRequestDefaults'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Sync Changes
Hide This Notification
Code changed:
Hide
1
2
Previous Highlighted Error
Next Highlighted Error
<?php
declare(strict_types=1);
namespace Jiminny\Http\Controllers\API\V2;
use Exception;
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Routing\Controller;
use Illuminate\Validation\ValidationException;
use Jiminny\Component\ActivitySearch\Service\ActivitySearch;
use Jiminny\Component\AskAnything\HistoryService;
use Jiminny\Component\AskJiminnyAi\Exceptions\AskJiminnyException;
use Jiminny\Component\AskJiminnyAi\OnDemandLevel\Events\AskAnythingAbortedChatCompleted;
use Jiminny\Component\Prophet\ProphetService;
use Jiminny\Component\ProphetAi\StreamRequest;
use Jiminny\Events\EventDispatcher;
use Jiminny\Exceptions\ActivityProviderException;
use Jiminny\Http\Requests\API\V2\OnDemandAskAnythingRequest;
use Jiminny\Models\Feature\FeatureEnum;
use Jiminny\Models\User;
use Jiminny\Repositories\ActiveStreamsRepository;
use Jiminny\Repositories\ElasticActivityRepository;
use Jiminny\Repositories\TeamAiContextRepository;
use Jiminny\Utils\FilterNormalizer;
use Jiminny\VO;
use Psr\Log\LoggerInterface;
use Symfony\Component\HttpFoundation\Response as ResponseAlias;
use Symfony\Component\HttpFoundation\StreamedResponse;
class OnDemandV2Controller extends Controller
{
use AuthorizesRequests;
private const int DEFAULT_TOP_ACTIVITIES_COUNT = 100;
private const array FILTER_KEY_EXCLUDED_PARAMS = [
'sequence_number',
'page',
'per_page',
'limit',
'offset',
];
public function __construct(
private readonly ActivitySearch $activitySearch,
private readonly HistoryService $historyService,
private readonly ProphetService $prophetService,
private readonly TeamAiContextRepository $teamAiContextRepository,
private readonly ActiveStreamsRepository $activeStreamsRepository,
private readonly EventDispatcher $eventDispatcher,
private readonly LoggerInterface $logger,
) {
}
/**
* Check if the user's team has the ASK_JIMINNY_ON_ANYTHING feature enabled
*/
private function checkAskJiminnyOnAnythingFeature(User $user): ?JsonResponse
{
if (! $user->team->hasFeature(FeatureEnum::ASK_JIMINNY_ON_ANYTHING)) {
return new JsonResponse([
'message' => 'Feature ASK_JIMINNY_ON_ANYTHING is not enabled for this team',
], ResponseAlias::HTTP_FORBIDDEN);
}
return null;
}
/**
* Get top N activity IDs for Ask Jiminny feature based on filters
*
* @throws ValidationException
* @throws ActivityProviderException
*/
public function getContextForAskAnythingByFilter(Request $request, ElasticActivityRepository $repository): JsonResponse
{
/** @var User $user */
$user = $request->user();
if ($featureCheck = $this->checkAskJiminnyOnAnythingFeature($user)) {
return $featureCheck;
}
$topCount = $request->input('top_count', self::DEFAULT_TOP_ACTIVITIES_COUNT);
try {
// Always fetch first N (top count) IDs
$onDemandActivitySearchCriteria = VO\Repository\OnDemandActivitySearch\Criteria::createFromRequest(
array_merge($request->all(), ['limit' => $topCount, 'page' => 1]),
$user->getTimezone()
);
$filterSet = $this->activitySearch->getOnDemandPageFilterSet($onDemandActivitySearchCriteria, $user);
$validationRules = $filterSet->getValidationRules()
->merge([
'exclude' => 'array',
'limit' => 'integer|min:1|max:' . $topCount,
])
->all();
$request->validate($validationRules);
$hasChangedFilters = $this->hasChangedContextFilter($request, $user);
$activityIds = $repository->onDemandSearchIdsOnly($user, $onDemandActivitySearchCriteria, $filterSet);
$this->historyService->storeContextIds($user, HistoryService::CONTEXT_IDS, $activityIds);
return new JsonResponse([
'count' => count($activityIds),
'changed_context_filters' => $hasChangedFilters,
], ResponseAlias::HTTP_OK);
} catch (Exception $e) {
$this->logger->error('Failed to fetch activity IDs for Ask Jiminny', [
'error' => $e->getMessage(),
'user_id' => $user->getId(),
]);
return new JsonResponse([
'ids' => [],
'error' => 'Failed to fetch activity IDs',
], ResponseAlias::HTTP_INTERNAL_SERVER_ERROR);
}
}
private function hasChangedContextFilter(Request $request, User $user): bool
{
$filterKey = $this->makeFilterKey($request);
$result = $this->historyService->compareAndSetFilterKeyWithHistory($user, $filterKey);
if (! $result['changed']) {
return false;
}
if ($result['matches_previous']) {
return false;
}
$history = $this->historyService->getHistory($user, HistoryService::ON_DEMAND_SERVICE);
// If no history or last event already matches, return false
if (empty($history) || $this->historyService->hasFilteredChangedEventAsLastMessage($history)) {
return false;
}
// Append event and notify
$this->historyService->appendToEventHistory(
user: $user,
identifier: HistoryService::ON_DEMAND_SERVICE,
type: HistoryService::EVENT_FILTERS_CHANGED_TYPE
);
return true;
}
private function makeFilterKey(Request $request): string
{
$filters = $request->except(self::FILTER_KEY_EXCLUDED_PARAMS);
try {
$normalizedFilters = FilterNormalizer::normalizeFilters($filters);
$json = json_encode(
$normalizedFilters,
JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE | JSON_THROW_ON_ERROR
);
return hash('xxh3', $json);
} catch (\JsonException $e) {
$this->logger->error('Failed to encode filters', [
'error' => $e->getMessage(),
'filters_keys' => array_keys($filters),
]);
throw new AskJiminnyException('Failed to create filter key', 0, $e);
}
}
/**
* Get Ask Anything conversation history
*/
public function getAskAnythingHistory(Request $request): JsonResponse
{
/** @var User $user */
$user = $request->user();
if ($featureCheck = $this->checkAskJiminnyOnAnythingFeature($user)) {
return $featureCheck;
}
try {
$history = $this->historyService->getHistory($user, HistoryService::ON_DEMAND_SERVICE);
return new JsonResponse($history, ResponseAlias::HTTP_OK);
} catch (Exception $e) {
$this->logger->error('Failed to fetch Ask Anything history', [
'error' => $e->getMessage(),
'user_id' => $user->getId(),
]);
return new JsonResponse([
'history' => [],
'error' => 'Failed to fetch history',
], ResponseAlias::HTTP_INTERNAL_SERVER_ERROR);
}
}
/**
* Delete Ask Anything conversation history
*/
public function deleteAskAnythingHistory(Request $request): JsonResponse
{
/** @var User $user */
$user = $request->user();
if ($featureCheck = $this->checkAskJiminnyOnAnythingFeature($user)) {
return $featureCheck;
}
try {
$this->historyService->deleteHistory($user, HistoryService::ON_DEMAND_SERVICE);
return new JsonResponse([
'message' => 'History deleted successfully',
], ResponseAlias::HTTP_OK);
} catch (Exception $e) {
$this->logger->error('Failed to delete Ask Anything history', [
'error' => $e->getMessage(),
'user_id' => $user->getId(),
]);
return new JsonResponse([
'error' => 'Failed to delete history',
], ResponseAlias::HTTP_INTERNAL_SERVER_ERROR);
}
}
/**
* Ask Anything - submit question and get AI response
*/
public function askAnything(OnDemandAskAnythingRequest $request): StreamedResponse|JsonResponse
{
/** @var User $user */
$user = $request->user();
$this->logger->info('AskAnything request received', [
'user_id' => $user->getId(),
'team_id' => $user->getTeamId(),
'request_hash' => md5($request->input('message') . $user->getId() . floor(time() / 60)),
'message_preview' => mb_substr($request->input('message'), 0, 50),
]);
if ($featureCheck = $this->checkAskJiminnyOnAnythingFeature($user)) {
return $featureCheck;
}
try {
$inputData = $request->validated();
$requestData = [
'userQuestion' => $inputData['message'],
'callIds' => $this->historyService->getContextIds($user, HistoryService::CONTEXT_IDS),
'history' => $this->historyService->getHistory($user, HistoryService::ON_DEMAND_SERVICE),
];
$teamAiContext = $this->teamAiContextRepository->getByTeamId($user->getTeamId());
if ($teamAiContext?->getPrompt() !== null) {
$requestData['teamAiContext'] = $teamAiContext->getPrompt();
}
$this->historyService->appendToUserHistory(
$user,
HistoryService::ON_DEMAND_SERVICE,
$inputData['message']
);
$this->historyService->appendToEventHistory(
user: $user,
identifier: HistoryService::ON_DEMAND_SERVICE,
type: HistoryService::EVENT_IN_PROGRESS_TYPE
);
$streamRequest = StreamRequest::onDemandLevel($requestData);
// Track active stream in Redis
$this->activeStreamsRepository->start(
$user->getId(),
$streamRequest->getId(),
ttlSeconds: $streamRequest->getConnectTimeout() + $streamRequest->getReadTimeout()
);
return $this->prophetService->getStreamedOrAbortedResponse(
streamRequest: $streamRequest,
onCompleted: function (
string $assistantResponse,
bool $clientAborted,
bool $hadError,
) use ($user, $streamRequest) {
// Remove in-progress event
$this->historyService->removeLastEventMessageByType(
$user,
HistoryService::ON_DEMAND_SERVICE,
HistoryService::EVENT_IN_PROGRESS_TYPE
);
// Save to history if backend completed successfully (even if client disconnected)
// Only skip saving if there was an actual error during streaming
if (! $hadError && ! empty(trim($assistantResponse))) {
$this->historyService->appendToSystemHistory(
$user,
HistoryService::ON_DEMAND_SERVICE,
$assistantResponse,
);
}
// Notify frontend if client disconnected (so it can update UI if still on page)
if ($clientAborted) {
$this->eventDispatcher->dispatch(
new AskAnythingAbortedChatCompleted(
user: $user,
identifier: HistoryService::ON_DEMAND_SERVICE,
response: $assistantResponse,
)
);
}
// Remove active stream in Redis
$this->activeStreamsRepository->stop($user->getId(), $streamRequest->getId());
}
);
} catch (Exception $e) {
$this->historyService->removeLastEventMessageByType(
$user,
HistoryService::ON_DEMAND_SERVICE,
HistoryService::EVENT_IN_PROGRESS_TYPE
);
$this->logger->error('Failed to process Ask Anything request', [
'error' => $e->getMessage(),
'user_id' => $user->getId(),
'question' => $request->input('message'),
]);
return new JsonResponse([
'error' => 'Failed to process your question',
], ResponseAlias::HTTP_INTERNAL_SERVER_ERROR);
}
}
public function stopStream(Request $request): JsonResponse
{
$user = $request->user();
$this->activeStreamsRepository->stopByUser($user->getId());
$this->historyService->removeLastEventMessageByType(
$user,
HistoryService::ON_DEMAND_SERVICE,
HistoryService::EVENT_IN_PROGRESS_TYPE
);
return response()->json(['message' => 'Stream marked as stopped by user']);
}
}
Sync Changes
Hide This Notification
Code changed:
Hide
15
4
Previous Highlighted Error
Next Highlighted Error
<?php
declare(strict_types=1);
namespace Jiminny\Repositories;
use Carbon\CarbonImmutable;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Support\Carbon;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Pagination\LengthAwarePaginator;
use Illuminate\Support\Facades\DB;
use Jiminny\Models\AutomatedReport;
use Jiminny\Models\AutomatedReportResult;
use Jiminny\Models\Team;
use Jiminny\Models\User;
use Jiminny\Services\Kiosk\AutomatedReports\AutomatedReportsService;
use Jiminny\Services\Kiosk\AutomatedReports\ReportSort;
use Jiminny\Services\Kiosk\AutomatedReports\ReportSortDirection;
class AutomatedReportsRepository
{
/**
* Create a new automated report
*
* @param array $data
*
* @return AutomatedReport
*/
public function create(array $data): AutomatedReport
{
return AutomatedReport::create($data);
}
/**
* Find an automated report by UUID
*
* @param string $uuid
*
* @return AutomatedReport|null
*/
public function findByUuid(string $uuid): ?AutomatedReport
{
return AutomatedReport::where('uuid', AutomatedReport::toOptimized($uuid))->first();
}
public function findByIdOrUuid(string $idOrUuid): ?AutomatedReport
{
if (is_numeric($idOrUuid)) {
return AutomatedReport::find((int) $idOrUuid);
}
return AutomatedReport::where('uuid', AutomatedReport::toOptimized($idOrUuid))->first();
}
/**
* Retrieve all standard (non-Ask Jiminny) automated reports.
*
* @param string $sortColumn The column to sort by. Allowed values: 'created_by', 'created_at'. Defaults to 'created_at'.
* @param string $sortDirection The sort direction. Allowed values: 'asc', 'desc'. Defaults to 'desc'.
*
* @return Collection<AutomatedReport>
*/
public function getAllStandardReports(
string $sortColumn = 'created_at',
string $sortDirection = 'desc'
): Collection {
return $this->buildSortedQuery($sortColumn, $sortDirection)
->whereNot('type', AutomatedReportsService::TYPE_ASK_JIMINNY)
->get();
}
/**
* Retrieve all Ask Jiminny reports created by the given user.
*
* @param User $user The user whose reports to retrieve.
* @param string $sortColumn The column to sort by. Allowed values: 'created_by', 'created_at'. Defaults to 'created_at'.
* @param string $sortDirection The sort direction. Allowed values: 'asc', 'desc'. Defaults to 'desc'.
*
* @return Collection<AutomatedReport>
*/
public function getAskJiminnyReportsByUser(
User $user,
string $sortColumn = 'created_at',
string $sortDirection = 'desc'
): Collection {
return $this->buildSortedQuery($sortColumn, $sortDirection)
->where('type', AutomatedReportsService::TYPE_ASK_JIMINNY)
->where('created_by', $user->getId())
->get();
}
private function buildSortedQuery(string $sortColumn, string $sortDirection): \Illuminate\Database\Eloquent\Builder
{
$allowedColumns = ['created_by', 'created_at'];
if (! in_array($sortColumn, $allowedColumns)) {
$sortColumn = 'created_at';
}
$sortDirection = strtolower($sortDirection) === 'asc' ? 'asc' : 'desc';
$query = AutomatedReport::query()->with(['creator', 'team']);
if ($sortColumn === 'created_by') {
$query->leftJoin('users', 'users.id', '=', 'automated_reports.created_by')
->orderByRaw("users.name COLLATE utf8mb4_unicode_ci {$sortDirection}")
->select('automated_reports.*');
} else {
$query->orderBy($sortColumn, $sortDirection);
}
return $query;
}
/**
* Get all active and enabled reports with active teams for the specified frequency.
*
* @param string $frequency
*
* @return Collection<AutomatedReport>
*/
public function getActiveReportsByFrequency(string $frequency): Collection
{
return AutomatedReport::where('automated_reports.status', true)
->where('automated_reports.frequency', $frequency)
->join('teams', 'automated_reports.team_id', '=', 'teams.id')
->where('teams.status', Team::STATUS_ACTIVE)
->where(function ($query) {
$query->whereNull('automated_reports.expires_at')
->orWhere('automated_reports.expires_at', '>=', now()->toDateString());
})
->select('automated_reports.*')
->get();
}
/**
* Update an automated report
*
* @param AutomatedReport $report
* @param array $data
*
* @return AutomatedReport
*/
public function update(AutomatedReport $report, array $data): AutomatedReport
{
$report->update($data);
return $report;
}
/**
* Create a new automated report result.
*
* @param array $data The data to create the automated report result with.
*
* @return AutomatedReportResult The newly created automated report result.
*/
public function createResult(array $data): AutomatedReportResult
{
return AutomatedReportResult::create($data);
}
/**
* Find an automated report result by UUID.
*
* @param string $uuid The UUID to find the automated report result with.
*
* @return AutomatedReportResult|null The automated report result if found, otherwise null.
*/
public function findResultByUuid(string $uuid): ?AutomatedReportResult
{
return AutomatedReportResult::where('uuid', AutomatedReportResult::toOptimized($uuid))->first();
}
public function findResultByUuidForUser(string $uuid, User $user): ?AutomatedReportResult
{
return AutomatedReportResult::query()
->where('uuid', AutomatedReportResult::toOptimized($uuid))
->whereHas('report', static function ($query) use ($user): void {
$query->where('team_id', $user->getTeamId())
->where('created_by', $user->getId());
})
->first();
}
public function findChildResult(AutomatedReportResult $result, string $type): ?AutomatedReportResult
{
return AutomatedReportResult::query()
->where('parent_id', $result->getId())
->where('media_type', $type)
->first();
}
public function getGeneratedNotSentResults(): Collection
{
return AutomatedReportResult::query()
->whereNotNull('generated_at')
->whereNull('sent_at')
->where('status', AutomatedReportResult::STATUS_GENERATED)
->whereHas('report')
->with('report')
->get();
}
public function getPaginatedUserReports(
User $user,
ReportSort $sort,
ReportSortDirection $sortDirection,
int $resultsPerPage,
int $page,
?Carbon $fromDate,
?Carbon $toDate,
array $teamIds,
array $reportTypes,
?string $name,
): LengthAwarePaginator {
$query = AutomatedReportResult::query()
->whereNotNull('automated_report_results.generated_at')
->join('automated_reports', 'automated_report_results.report_id', '=', 'automated_reports.id')
->where('automated_reports.team_id', $user->getTeamId())
->whereJsonContains('automated_reports.recipients->users', $user->getId())
->orderByRaw("$sort->value COLLATE utf8mb4_unicode_ci {$sortDirection->value}")
->select('automated_report_results.*')
->with('report.team');
if ($fromDate !== null && $toDate !== null) {
$query->whereBetween('generated_at', [$fromDate, $toDate]);
}
if (! empty($teamIds)) {
$query->where(function ($q) use ($teamIds) {
foreach ($teamIds as $id) {
$q->orWhereJsonContains('automated_reports.groups', $id);
}
});
}
if (! empty($reportTypes)) {
$query->whereIn('automated_reports.type', $reportTypes);
}
if (! empty($name)) {
$query->whereLike('name', "%$name%");
}
return $query->paginate($resultsPerPage, ['*'], 'page', $page);
}
public function countUserReports(User $user): int
{
return AutomatedReportResult::query()
->whereNotNull('generated_at')
->whereNotNull('sent_at')
->whereHas('report', function ($q) use ($user) {
$q->where('team_id', $user->getTeamId())
->whereJsonContains('recipients->users', $user->getId());
})
->count();
}
/**
* Get report IDs for a specific team
*
* @param Team $team
*
* @return \Illuminate\Support\Collection
*/
public function getReportIdsByTeam(Team $team): \Illuminate\Support\Collection
{
return AutomatedReport::where('team_id', $team->getId())->pluck('id');
}
/**
* Get all reports for a specific team
*
* @param Team $team
*
* @return Collection
*/
public function getReportsByTeam(Team $team): Collection
{
return AutomatedReport::where('team_id', $team->getId())->get();
}
/**
* Get all report results for a specific report
*
* @param AutomatedReport $report
*
* @return Collection
*/
public function getResultsByReport(AutomatedReport $report): Collection
{
return $this->getResultsByReportQuery($report)->get();
}
public function getResultsByReportQuery(AutomatedReport $report): Builder
{
return AutomatedReportResult::where('report_id', $report->getId());
}
public function getReportResultsQueryForRetention(Team $team, CarbonImmutable $retentionDate): Builder
{
$reportIds = $this->getReportIdsByTeam($team);
return AutomatedReportResult::query()->whereIn('report_id', $reportIds)
->whereRaw('IFNULL(generated_at, created_at) <= ?', [$retentionDate]);
}
/**
* @param int|null $teamId Optional team ID to filter results
*
* @return \Illuminate\Support\Collection<int, int> Collection of team IDs
*/
public function getTeamIdsWithReportsResults(?int $teamId = null): \Illuminate\Support\Collection
{
$query = DB::table('automated_reports')
->join('teams', 'automated_reports.team_id', '=', 'teams.id')
->select('teams.id')
->distinct();
if ($teamId !== null) {
$query->where('teams.id', $teamId);
}
return $query->pluck('teams.id');
}
}
Project
Project
New File or Directory…
Expand Selected
Collapse All
Options
Hide
app ~/jiminny/app
.circleci
.cursor
.github
.sonarlint
.vscode
.windsurf
app, sources root
Actions
Component...
|
PhpStorm
|
faVsco.js – OnDemandV2Controller.php
|
NULL
|
11088
|
|
11087
|
Project: faVsco.js, menu
#11894 on JY-18909-automa Project: faVsco.js, menu
#11894 on JY-18909-automated-reports-ask-jiminny, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceT…Defaults
Run 'AskJiminnyReportActivityServiceTest.tes…uenceNumberToDisableFirstRequestDefaults'
Debug 'AskJiminnyReportActivityServiceTest.tes…uenceNumberToDisableFirstRequestDefaults'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Sync Changes
Hide This Notification
Code changed:
Hide
1
2
Previous Highlighted Error
Next Highlighted Error
<?php
declare(strict_types=1);
namespace Jiminny\Http\Controllers\API\V2;
use Exception;
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Routing\Controller;
use Illuminate\Validation\ValidationException;
use Jiminny\Component\ActivitySearch\Service\ActivitySearch;
use Jiminny\Component\AskAnything\HistoryService;
use Jiminny\Component\AskJiminnyAi\Exceptions\AskJiminnyException;
use Jiminny\Component\AskJiminnyAi\OnDemandLevel\Events\AskAnythingAbortedChatCompleted;
use Jiminny\Component\Prophet\ProphetService;
use Jiminny\Component\ProphetAi\StreamRequest;
use Jiminny\Events\EventDispatcher;
use Jiminny\Exceptions\ActivityProviderException;
use Jiminny\Http\Requests\API\V2\OnDemandAskAnythingRequest;
use Jiminny\Models\Feature\FeatureEnum;
use Jiminny\Models\User;
use Jiminny\Repositories\ActiveStreamsRepository;
use Jiminny\Repositories\ElasticActivityRepository;
use Jiminny\Repositories\TeamAiContextRepository;
use Jiminny\Utils\FilterNormalizer;
use Jiminny\VO;
use Psr\Log\LoggerInterface;
use Symfony\Component\HttpFoundation\Response as ResponseAlias;
use Symfony\Component\HttpFoundation\StreamedResponse;
class OnDemandV2Controller extends Controller
{
use AuthorizesRequests;
private const int DEFAULT_TOP_ACTIVITIES_COUNT = 100;
private const array FILTER_KEY_EXCLUDED_PARAMS = [
'sequence_number',
'page',
'per_page',
'limit',
'offset',
];
public function __construct(
private readonly ActivitySearch $activitySearch,
private readonly HistoryService $historyService,
private readonly ProphetService $prophetService,
private readonly TeamAiContextRepository $teamAiContextRepository,
private readonly ActiveStreamsRepository $activeStreamsRepository,
private readonly EventDispatcher $eventDispatcher,
private readonly LoggerInterface $logger,
) {
}
/**
* Check if the user's team has the ASK_JIMINNY_ON_ANYTHING feature enabled
*/
private function checkAskJiminnyOnAnythingFeature(User $user): ?JsonResponse
{
if (! $user->team->hasFeature(FeatureEnum::ASK_JIMINNY_ON_ANYTHING)) {
return new JsonResponse([
'message' => 'Feature ASK_JIMINNY_ON_ANYTHING is not enabled for this team',
], ResponseAlias::HTTP_FORBIDDEN);
}
return null;
}
/**
* Get top N activity IDs for Ask Jiminny feature based on filters
*
* @throws ValidationException
* @throws ActivityProviderException
*/
public function getContextForAskAnythingByFilter(Request $request, ElasticActivityRepository $repository): JsonResponse
{
/** @var User $user */
$user = $request->user();
if ($featureCheck = $this->checkAskJiminnyOnAnythingFeature($user)) {
return $featureCheck;
}
$topCount = $request->input('top_count', self::DEFAULT_TOP_ACTIVITIES_COUNT);
try {
// Always fetch first N (top count) IDs
$onDemandActivitySearchCriteria = VO\Repository\OnDemandActivitySearch\Criteria::createFromRequest(
array_merge($request->all(), ['limit' => $topCount, 'page' => 1]),
$user->getTimezone()
);
$filterSet = $this->activitySearch->getOnDemandPageFilterSet($onDemandActivitySearchCriteria, $user);
$validationRules = $filterSet->getValidationRules()
->merge([
'exclude' => 'array',
'limit' => 'integer|min:1|max:' . $topCount,
])
->all();
$request->validate($validationRules);
$hasChangedFilters = $this->hasChangedContextFilter($request, $user);
$activityIds = $repository->onDemandSearchIdsOnly($user, $onDemandActivitySearchCriteria, $filterSet);
$this->historyService->storeContextIds($user, HistoryService::CONTEXT_IDS, $activityIds);
return new JsonResponse([
'count' => count($activityIds),
'changed_context_filters' => $hasChangedFilters,
], ResponseAlias::HTTP_OK);
} catch (Exception $e) {
$this->logger->error('Failed to fetch activity IDs for Ask Jiminny', [
'error' => $e->getMessage(),
'user_id' => $user->getId(),
]);
return new JsonResponse([
'ids' => [],
'error' => 'Failed to fetch activity IDs',
], ResponseAlias::HTTP_INTERNAL_SERVER_ERROR);
}
}
private function hasChangedContextFilter(Request $request, User $user): bool
{
$filterKey = $this->makeFilterKey($request);
$result = $this->historyService->compareAndSetFilterKeyWithHistory($user, $filterKey);
if (! $result['changed']) {
return false;
}
if ($result['matches_previous']) {
return false;
}
$history = $this->historyService->getHistory($user, HistoryService::ON_DEMAND_SERVICE);
// If no history or last event already matches, return false
if (empty($history) || $this->historyService->hasFilteredChangedEventAsLastMessage($history)) {
return false;
}
// Append event and notify
$this->historyService->appendToEventHistory(
user: $user,
identifier: HistoryService::ON_DEMAND_SERVICE,
type: HistoryService::EVENT_FILTERS_CHANGED_TYPE
);
return true;
}
private function makeFilterKey(Request $request): string
{
$filters = $request->except(self::FILTER_KEY_EXCLUDED_PARAMS);
try {
$normalizedFilters = FilterNormalizer::normalizeFilters($filters);
$json = json_encode(
$normalizedFilters,
JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE | JSON_THROW_ON_ERROR
);
return hash('xxh3', $json);
} catch (\JsonException $e) {
$this->logger->error('Failed to encode filters', [
'error' => $e->getMessage(),
'filters_keys' => array_keys($filters),
]);
throw new AskJiminnyException('Failed to create filter key', 0, $e);
}
}
/**
* Get Ask Anything conversation history
*/
public function getAskAnythingHistory(Request $request): JsonResponse
{
/** @var User $user */
$user = $request->user();
if ($featureCheck = $this->checkAskJiminnyOnAnythingFeature($user)) {
return $featureCheck;
}
try {
$history = $this->historyService->getHistory($user, HistoryService::ON_DEMAND_SERVICE);
return new JsonResponse($history, ResponseAlias::HTTP_OK);
} catch (Exception $e) {
$this->logger->error('Failed to fetch Ask Anything history', [
'error' => $e->getMessage(),
'user_id' => $user->getId(),
]);
return new JsonResponse([
'history' => [],
'error' => 'Failed to fetch history',
], ResponseAlias::HTTP_INTERNAL_SERVER_ERROR);
}
}
/**
* Delete Ask Anything conversation history
*/
public function deleteAskAnythingHistory(Request $request): JsonResponse
{
/** @var User $user */
$user = $request->user();
if ($featureCheck = $this->checkAskJiminnyOnAnythingFeature($user)) {
return $featureCheck;
}
try {
$this->historyService->deleteHistory($user, HistoryService::ON_DEMAND_SERVICE);
return new JsonResponse([
'message' => 'History deleted successfully',
], ResponseAlias::HTTP_OK);
} catch (Exception $e) {
$this->logger->error('Failed to delete Ask Anything history', [
'error' => $e->getMessage(),
'user_id' => $user->getId(),
]);
return new JsonResponse([
'error' => 'Failed to delete history',
], ResponseAlias::HTTP_INTERNAL_SERVER_ERROR);
}
}
/**
* Ask Anything - submit question and get AI response
*/
public function askAnything(OnDemandAskAnythingRequest $request): StreamedResponse|JsonResponse
{
/** @var User $user */
$user = $request->user();
$this->logger->info('AskAnything request received', [
'user_id' => $user->getId(),
'team_id' => $user->getTeamId(),
'request_hash' => md5($request->input('message') . $user->getId() . floor(time() / 60)),
'message_preview' => mb_substr($request->input('message'), 0, 50),
]);
if ($featureCheck = $this->checkAskJiminnyOnAnythingFeature($user)) {
return $featureCheck;
}
try {
$inputData = $request->validated();
$requestData = [
'userQuestion' => $inputData['message'],
'callIds' => $this->historyService->getContextIds($user, HistoryService::CONTEXT_IDS),
'history' => $this->historyService->getHistory($user, HistoryService::ON_DEMAND_SERVICE),
];
$teamAiContext = $this->teamAiContextRepository->getByTeamId($user->getTeamId());
if ($teamAiContext?->getPrompt() !== null) {
$requestData['teamAiContext'] = $teamAiContext->getPrompt();
}
$this->historyService->appendToUserHistory(
$user,
HistoryService::ON_DEMAND_SERVICE,
$inputData['message']
);
$this->historyService->appendToEventHistory(
user: $user,
identifier: HistoryService::ON_DEMAND_SERVICE,
type: HistoryService::EVENT_IN_PROGRESS_TYPE
);
$streamRequest = StreamRequest::onDemandLevel($requestData);
// Track active stream in Redis
$this->activeStreamsRepository->start(
$user->getId(),
$streamRequest->getId(),
ttlSeconds: $streamRequest->getConnectTimeout() + $streamRequest->getReadTimeout()
);
return $this->prophetService->getStreamedOrAbortedResponse(
streamRequest: $streamRequest,
onCompleted: function (
string $assistantResponse,
bool $clientAborted,
bool $hadError,
) use ($user, $streamRequest) {
// Remove in-progress event
$this->historyService->removeLastEventMessageByType(
$user,
HistoryService::ON_DEMAND_SERVICE,
HistoryService::EVENT_IN_PROGRESS_TYPE
);
// Save to history if backend completed successfully (even if client disconnected)
// Only skip saving if there was an actual error during streaming
if (! $hadError && ! empty(trim($assistantResponse))) {
$this->historyService->appendToSystemHistory(
$user,
HistoryService::ON_DEMAND_SERVICE,
$assistantResponse,
);
}
// Notify frontend if client disconnected (so it can update UI if still on page)
if ($clientAborted) {
$this->eventDispatcher->dispatch(
new AskAnythingAbortedChatCompleted(
user: $user,
identifier: HistoryService::ON_DEMAND_SERVICE,
response: $assistantResponse,
)
);
}
// Remove active stream in Redis
$this->activeStreamsRepository->stop($user->getId(), $streamRequest->getId());
}
);
} catch (Exception $e) {
$this->historyService->removeLastEventMessageByType(
$user,
HistoryService::ON_DEMAND_SERVICE,
HistoryService::EVENT_IN_PROGRESS_TYPE
);
$this->logger->error('Failed to process Ask Anything request', [
'error' => $e->getMessage(),
'user_id' => $user->getId(),
'question' => $request->input('message'),
]);
return new JsonResponse([
'error' => 'Failed to process your question',
], ResponseAlias::HTTP_INTERNAL_SERVER_ERROR);
}
}
public function stopStream(Request $request): JsonResponse
{
$user = $request->user();
$this->activeStreamsRepository->stopByUser($user->getId());
$this->historyService->removeLastEventMessageByType(
$user,
HistoryService::ON_DEMAND_SERVICE,
HistoryService::EVENT_IN_PROGRESS_TYPE
);
return response()->json(['message' => 'Stream marked as stopped by user']);
}
}
Sync Changes
Hide This Notification
Code changed:
Hide
15
4
Previous Highlighted Error
Next Highlighted Error
<?php
declare(strict_types=1);
namespace Jiminny\Repositories;
use Carbon\CarbonImmutable;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Support\Carbon;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Pagination\LengthAwarePaginator;
use Illuminate\Support\Facades\DB;
use Jiminny\Models\AutomatedReport;
use Jiminny\Models\AutomatedReportResult;
use Jiminny\Models\Team;
use Jiminny\Models\User;
use Jiminny\Services\Kiosk\AutomatedReports\AutomatedReportsService;
use Jiminny\Services\Kiosk\AutomatedReports\ReportSort;
use Jiminny\Services\Kiosk\AutomatedReports\ReportSortDirection;
class AutomatedReportsRepository
{
/**
* Create a new automated report
*
* @param array $data
*
* @return AutomatedReport
*/
public function create(array $data): AutomatedReport
{
return AutomatedReport::create($data);
}
/**
* Find an automated report by UUID
*
* @param string $uuid
*
* @return AutomatedReport|null
*/
public function findByUuid(string $uuid): ?AutomatedReport
{
return AutomatedReport::where('uuid', AutomatedReport::toOptimized($uuid))->first();
}
public function findByIdOrUuid(string $idOrUuid): ?AutomatedReport
{
if (is_numeric($idOrUuid)) {
return AutomatedReport::find((int) $idOrUuid);
}
return AutomatedReport::where('uuid', AutomatedReport::toOptimized($idOrUuid))->first();
}
/**
* Retrieve all standard (non-Ask Jiminny) automated reports.
*
* @param string $sortColumn The column to sort by. Allowed values: 'created_by', 'created_at'. Defaults to 'created_at'.
* @param string $sortDirection The sort direction. Allowed values: 'asc', 'desc'. Defaults to 'desc'.
*
* @return Collection<AutomatedReport>
*/
public function getAllStandardReports(
string $sortColumn = 'created_at',
string $sortDirection = 'desc'
): Collection {
return $this->buildSortedQuery($sortColumn, $sortDirection)
->whereNot('type', AutomatedReportsService::TYPE_ASK_JIMINNY)
->get();
}
/**
* Retrieve all Ask Jiminny reports created by the given user.
*
* @param User $user The user whose reports to retrieve.
* @param string $sortColumn The column to sort by. Allowed values: 'created_by', 'created_at'. Defaults to 'created_at'.
* @param string $sortDirection The sort direction. Allowed values: 'asc', 'desc'. Defaults to 'desc'.
*
* @return Collection<AutomatedReport>
*/
public function getAskJiminnyReportsByUser(
User $user,
string $sortColumn = 'created_at',
string $sortDirection = 'desc'
): Collection {
return $this->buildSortedQuery($sortColumn, $sortDirection)
->where('type', AutomatedReportsService::TYPE_ASK_JIMINNY)
->where('created_by', $user->getId())
->get();
}
private function buildSortedQuery(string $sortColumn, string $sortDirection): \Illuminate\Database\Eloquent\Builder
{
$allowedColumns = ['created_by', 'created_at'];
if (! in_array($sortColumn, $allowedColumns)) {
$sortColumn = 'created_at';
}
$sortDirection = strtolower($sortDirection) === 'asc' ? 'asc' : 'desc';
$query = AutomatedReport::query()->with(['creator', 'team']);
if ($sortColumn === 'created_by') {
$query->leftJoin('users', 'users.id', '=', 'automated_reports.created_by')
->orderByRaw("users.name COLLATE utf8mb4_unicode_ci {$sortDirection}")
->select('automated_reports.*');
} else {
$query->orderBy($sortColumn, $sortDirection);
}
return $query;
}
/**
* Get all active and enabled reports with active teams for the specified frequency.
*
* @param string $frequency
*
* @return Collection<AutomatedReport>
*/
public function getActiveReportsByFrequency(string $frequency): Collection
{
return AutomatedReport::where('automated_reports.status', true)
->where('automated_reports.frequency', $frequency)
->join('teams', 'automated_reports.team_id', '=', 'teams.id')
->where('teams.status', Team::STATUS_ACTIVE)
->where(function ($query) {
$query->whereNull('automated_reports.expires_at')
->orWhere('automated_reports.expires_at', '>=', now()->toDateString());
})
->select('automated_reports.*')
->get();
}
/**
* Update an automated report
*
* @param AutomatedReport $report
* @param array $data
*
* @return AutomatedReport
*/
public function update(AutomatedReport $report, array $data): AutomatedReport
{
$report->update($data);
return $report;
}
/**
* Create a new automated report result.
*
* @param array $data The data to create the automated report result with.
*
* @return AutomatedReportResult The newly created automated report result.
*/
public function createResult(array $data): AutomatedReportResult
{
return AutomatedReportResult::create($data);
}
/**
* Find an automated report result by UUID.
*
* @param string $uuid The UUID to find the automated report result with.
*
* @return AutomatedReportResult|null The automated report result if found, otherwise null.
*/
public function findResultByUuid(string $uuid): ?AutomatedReportResult
{
return AutomatedReportResult::where('uuid', AutomatedReportResult::toOptimized($uuid))->first();
}
public function findResultByUuidForUser(string $uuid, User $user): ?AutomatedReportResult
{
return AutomatedReportResult::query()
->where('uuid', AutomatedReportResult::toOptimized($uuid))
->whereHas('report', static function ($query) use ($user): void {
$query->where('team_id', $user->getTeamId())
->where('created_by', $user->getId());
})
->first();
}
public function findChildResult(AutomatedReportResult $result, string $type): ?AutomatedReportResult
{
return AutomatedReportResult::query()
->where('parent_id', $result->getId())
->where('media_type', $type)
->first();
}
public function getGeneratedNotSentResults(): Collection
{
return AutomatedReportResult::query()
->whereNotNull('generated_at')
->whereNull('sent_at')
->where('status', AutomatedReportResult::STATUS_GENERATED)
->whereHas('report')
->with('report')
->get();
}
public function getPaginatedUserReports(
User $user,
ReportSort $sort,
ReportSortDirection $sortDirection,
int $resultsPerPage,
int $page,
?Carbon $fromDate,
?Carbon $toDate,
array $teamIds,
array $reportTypes,
?string $name,
): LengthAwarePaginator {
$query = AutomatedReportResult::query()
->whereNotNull('automated_report_results.generated_at')
->join('automated_reports', 'automated_report_results.report_id', '=', 'automated_reports.id')
->where('automated_reports.team_id', $user->getTeamId())
->whereJsonContains('automated_reports.recipients->users', $user->getId())
->orderByRaw("$sort->value COLLATE utf8mb4_unicode_ci {$sortDirection->value}")
->select('automated_report_results.*')
->with('report.team');
if ($fromDate !== null && $toDate !== null) {
$query->whereBetween('generated_at', [$fromDate, $toDate]);
}
if (! empty($teamIds)) {
$query->where(function ($q) use ($teamIds) {
foreach ($teamIds as $id) {
$q->orWhereJsonContains('automated_reports.groups', $id);
}
});
}
if (! empty($reportTypes)) {
$query->whereIn('automated_reports.type', $reportTypes);
}
if (! empty($name)) {
$query->whereLike('name', "%$name%");
}
return $query->paginate($resultsPerPage, ['*'], 'page', $page);
}
public function countUserReports(User $user): int
{
return AutomatedReportResult::query()
->whereNotNull('generated_at')
->whereNotNull('sent_at')
->whereHas('report', function ($q) use ($user) {
$q->where('team_id', $user->getTeamId())
->whereJsonContains('recipients->users', $user->getId());
})
->count();
}
/**
* Get report IDs for a specific team
*
* @param Team $team
*
* @return \Illuminate\Support\Collection
*/
public function getReportIdsByTeam(Team $team): \Illuminate\Support\Collection
{
return AutomatedReport::where('team_id', $team->getId())->pluck('id');
}
/**
* Get all reports for a specific team
*
* @param Team $team
*
* @return Collection
*/
public function getReportsByTeam(Team $team): Collection
{
return AutomatedReport::where('team_id', $team->getId())->get();
}
/**
* Get all report results for a specific report
*
* @param AutomatedReport $report
*
* @return Collection
*/
public function getResultsByReport(AutomatedReport $report): Collection
{
return $this->getResultsByReportQuery($report)->get();
}
public function getResultsByReportQuery(AutomatedReport $report): Builder
{
return AutomatedReportResult::where('report_id', $report->getId());
}
public function getReportResultsQueryForRetention(Team $team, CarbonImmutable $retentionDate): Builder
{
$reportIds = $this->getReportIdsByTeam($team);
return AutomatedReportResult::query()->whereIn('report_id', $reportIds)
->whereRaw('IFNULL(generated_at, created_at) <= ?', [$retentionDate]);
}
/**
* @param int|null $teamId Optional team ID to filter results
*
* @return \Illuminate\Support\Collection<int, int> Collection of team IDs
*/
public function getTeamIdsWithReportsResults(?int $teamId = null): \Illuminate\Support\Collection
{
$query = DB::table('automated_reports')
->join('teams', 'automated_reports.team_id', '=', 'teams.id')
->select('teams.id')
->distinct();
if ($teamId !== null) {
$query->where('teams.id', $teamId);
}
return $query->pluck('teams.id');
}
}
Project
Project
New File or Directory…
Expand Selected
Collapse All
Options
Hide...
|
PhpStorm
|
faVsco.js – OnDemandV2Controller.php
|
NULL
|
11087
|
|
11086
|
PhpStormFileEditViewNavigateCodeLaravelRefactorFV PhpStormFileEditViewNavigateCodeLaravelRefactorFV faVsco.s v#11894 on JY-18909-automated-reports-ask-iminny K vProject vToolsWindowHelp© JiminnyDebugCommanc© JiminnySetEncryptedTo© JiminnyTokenInfoComm© MakeSlackLiveCoachins© ManageScimForTeam.p(c Malkoanchrorenvironnc Mureu canzercnanner© PhpApm.php© PropagateCoachingFeer© PurgeConferences.php© PurgeSoftDeletedOppor© PurgeSyncBatchesComiC RecalculateDealRisksCa© RemoveDeleteMarkersC© RemoveExpiredNudgesi© RemoveUnusedParticip:© ResetElasticSearch.php© RestoreActivityCrmProv© RestoreActivityTypeCor© SeedActivities.php© SyncActivity.php©Tracklmported.php© UpdateActivitiesAverag© WhichWorkerlsWorkingr> Scheduling© Kernel.phpM Contracts> M Domain> MDTO> M Emails› _ Enums> D Events> D Exceptions> DJ FFMpeg>D Formats› D Guards› C Helpersv UHttp> MAccessTokenProviderv @ ControllersV DAPI> D AiCallScoringAiReports> D Deallnsights> D Opportunity> C Page> • ScorecardsSettingsTeamInsightsnemes> MUserAutomatedRepov DV2C ACIMINVACOnTOAskAnythingCont© AskJiminnyReporl© DealsV2Controlle:© OnDemandV2Con© PlaylistController.© PlaylistShareCont© ReportController.php© AutomatedReportsCommand.phpJiminnybeouecommana.ong= custom.log< console EUi= laravel.logA SF [jiminny@localhost]A HS_local [jiminny@localhost]A console [PROD]console SlAGiNG© AskJiminnyReportActivityService.php© ActivitySearch.php© AutomatedReportsSendCommand.php© AddLayoutEntities.php© Team.php© AutomatedReportsRepository.php X© AutomatedReportsService.phpC CreateHeldActivityEvent.phpOnDemandV2Controller.php x © HistoryService.php© FilterDefinitionCollection.php© Criteria.php© AskJiminnyReportActivityServiceTest.phpC) RequestGenerateAskJiminnyReportJobTest.phpclass OnDemandV2ControllerControllerJubede Tuon getAsKAnycningniscory request srequesc: ssonkesponset...s41 X2 ^(e) TrackProvidernstallled-vent.ono© CreateActivityLoggedEvent.php© UserPilotActivityListener.php(©) ActivityLogged.phpAutomatedReportsCallbackService.php© RequestGenerateAskJiminnyReportJob.phpRequestGenerateReportJob.php© AutomatedReportResult.php(C) AutomatedReport.php18411208209210211/*** Delete Ask Anything conversation history212 Ц >public function deleteAskAnythingHistory(Request $request): JsonResponsef...}258class Automacedкeрortskepo o:A15 M4 A VLOY/*** A5k Anything - subnit question and get nesponse616276931141151161171181191211124123241 kg* Retrieve all standard (non-Ask Jiminny) m243244* @param string $sortColumnThe column to)245* dodron scrino osorcuurection ine sort oulre246247* @return Collection<AutomatedReport>24824912 usagespublic function getAllStandardReports(string $sortColumn = 'created_at',string $sortDirection = 'desc'): Collection {...}250251252253254255pubizo function askAnythangCOnDenandASKAnythangRequest goquest): StreanedResponse / JsonRes/** @var User $user */$user = $request->user();nunus→> loodelything request received', I'user_id' => $user-›getId().'team_id' => $user->getTeamId(),'request_hash' => md5 ( string: $request->input( key: 'message') • $user-›getId() . flor'message_preview' => mb_substr($request->input( key: 'message'), 0, 50),J):if ($featureCheck = $this->checkAskJiminnyOnAnythingFeature($user)) €return $featureCheck;/*** Retrieve all Ask Liminay reports created 257try {SinoutData = Srequest->validatedo:* Oodrdll usernusenIne user Ynos259* @param string $sortColumnThe column to* Oparam string $sortDirection The sort dire200261262* @return Collection<AutomatedReport>263*/— 26414 usages265public function getAskJiminnyReportsByUser(- 266User $user,267string $sortColumn = 'created_at',268string ssorcbirection = "desc"): Collection {...J$requestData = ['userQuestion' => $inputData[ 'message'],'callIds' => $this->historyService->getContextIds($user,identifier: HistoryServic'history' => $this->historyService->getHistory($user,identifier: HistoryService: :]:$teamAiContext = $this->teamAiContextRepository->getByTeamId($user->getTeamId());if ($teamAiContext?->getPrompt() !== null) {srequescbacal ceamAlcontext'. = preamAlcontext->getrrompt;—271Z usages272private function buildSortedQuery(string $sor273/**-274* Get all active and enabled reports with al276277* @param string $frequency278— 279$this->historyService->appendToUserHistory($user,identifier: HistoryService::0N_DEMAND_SERVICE,$inputData[ 'message']):* dreturh coLcectzon<aucomacedкeрort>$this->historyService->appendToEventHistory(user: $user,identifier: HistoryService::0N_DEMAND_SERVICE,type: HIscoryservice..EVENI_IN_PRUGRESS_TYPEZ81123 usagespublic function getActiveReportsByFrequency(s)184283gctnoamPonloct = CtnoamPonloct •onfomandiii ovo (ineauoctlatan•Tests passed: 1 (2 minutes ago), 0lablf Support Daily • in 2h 49 mAAskJiminnyReportActivityServiceT…Defaults100% C•Tue 14 Apr 12:11:52CascadeFixing ReportControllerAutomated Report MarFixing Ask Jiminny Rep+D..Now let's run the test to verifvwtests/Unxt/Servsces/Kiosk/Automate/meports/AskJ1minnyreportActivätyserviceTest-php --no-coveragecould not open input Tile: /var/www/ncml/artisandoster nxe ceockes /kJosk/AuP /ape/a/poras/A5kJ1minyReportActivityServiceTest.php --no-coverageCould not open input file: /app/artisanCommand dockerocker exec oocker lano oash—e"cd /var/www&& php artisan testLests unlu services Klosk Aucomaceakeporcs AskJiminnykeportAccivityservicelest.ono =-no-coverade D&l'Could not open input file: artisanCommand docken• docker exec docker_lamp_1 bash -c "find / -name artisan -maxdepth 6 2>/dev/null | head -5"/home/jiminny/artisan"cd /homee/jiminny && php artisan testtests/ext/ drvicrs/K2psk/Autonat eReports/A5KDiman ReportActivatyServiceTest,php --no-coverage 261"PASSgetTests\Unit\Services\Kiosk\AutomatedReports\AskJiminnyReportActivityServiceTesta fittersemoty when no resultsperiod date filters1de handtes scalyr flttersids bassess snazer fsequence number to disable first _ 0.025All 8 tests pass. Here's a summary:Root Cause & FixRoot cause: buildRequestParamsFromSearch never set sequence number in the request params, so Criteria::createFromRequest defaulted it to 0Since isFirstRequest() returns true when sequenceNumber === 0, several implicit defaults were silently applied:Activitvourat ionRande → min duration = 1 ilters ouf o-second activitiesiActivityRecorded → only_recorded = 1 (restricts to recorded activities only)OrganiserGroupIn → applies user's default group as a filtelThe frontend URL you noticed uses sequence_number=4, which disables these defaults - explaining why the frontend returned activities but the servicereturee o.Fix: AskJiminnyReportActivityService.php:51—added 'sequence_number' → 1 to the Criteria::createFromRequest merge, ensuring isFirstRequest() returns false and no implicit defaults are injected.Test added: testGetAct1cylasPassesNonzerosequencenumberloDisablerarsckequestberaulus assers that the captured uriteria ob ect nas 1srirstRequest() === false.Öul ..Vew allliItlle wiun changesvapp/Services/Kiosk/AutomatedReports/D AskJiminnyReportActivityService.php +1 -1Reject allAccept allExplain it to me again. Why is there issue with that? Where is it expected and wy do l need to fork with that. How is it used in+ <> Code Claude Sonnet 4.6W Windsurf Teams203:49uir-o( 4 spaces...
|
NULL
|
NULL
|
NULL
|
11086
|
|
11085
|
+SlackEDHomeDMSActivityFilesLater..•More+FileEditV +SlackEDHomeDMSActivityFilesLater..•More+FileEditViewGoHistoryWindowHelpJiminny ...# Starredplatform-inner-teamChannels# ai-chapter# alerts# backend# confusion-clinic# curiosity_lab# engineering# frontend# general# infra-changes# jiminny-bg# platform-tickets# product_launches# random# releases# sofia-office# support# thank-yous# the_people_of jimi…..Direct messagesAneliya Angelova, ...Steliyan GeorgievAdelina Petrova, Ili.... Adelina PetrovaO. Calea Dimitravo→Search Jiminny IncAneliya Angelova, Nikolay Yankov, Steliyan GeorgievMessagesAdd canvas+Nikolay Yankov 10:45 AMпиши кат оя рьннешLukas Kovalik 10:52 AMзабавих се че ми се разбазикаха settings за средипуснах и мина и fail-наима result но e failedзначиREASON_NOT_ENOUGH_ACTIVITIESвиж дали има нещо в OD със този филтьрNikolay Yankov 11:01 AMДобреNikolay Yankov 11:39 AMя рьнни пак LukasLukas Kovalik 11:43 AMготовосьщотоCompetitive pitches беше втория нали такаNikolay Yankov 12:04 PMДа, там има 14 активитита, защо не сработи този пьт?Lukas Kovalik 12:05 PMпак изглежда sequenceгледам гоMessage Aneliya Angelova, Nikolay Yankov, Steliyan Georgiev+Aalal]Support Daily - in 2h 49 m100% <47Tue 14 Apr 12:11:528Today ~...
|
NULL
|
NULL
|
NULL
|
11085
|
|
11084
|
PhpStormFileEditViewNavigateCodeLaravelRefactorFV PhpStormFileEditViewNavigateCodeLaravelRefactorFV faVsco.s v#11894 on JY-18909-automated-reports-ask-liminny k vProject vToolsWindowHelp© JiminnyDebugCommanc© JiminnySetEncryptedTo© JiminnyTokenInfoComm© MakeSlackLiveCoachins© Managescim-orleam.p(c Malkoanchrocnvronnlc Mureu canzercnanner© PhpApm.php© PropagateCoachingFeer© PurgeConferences.php© PurgeSoftDeletedOppor© PurgeSyncBatchesComi© RecalculateDealRisksCa© RemoveDeleteMarkersC© RemoveExpiredNudgesi© RemoveUnusedParticip:© ResetElasticSearch.php© RestoreActivityCrmProv© RestoreActivityTypeCor© SeedActivities.php© SyncActivity.php©Tracklmported.php© UpdateActivitiesAverag© WhichWorkerlsWorkingr> Scheduling© Kernel.phpM Contracts> M Domain> MDTO> M Emails› _ Enums> D Events> D Exceptions> DJ FFMpeg>D Formats› D Guards› C Helpersv UHttp> MAccessTokenProviderv D ControllersV DAPI> D AiCallScoringAiReports> D Deallnsights> D Opportunity> C Page> • Scorecards> D SettingsTeamInsightsnemes> MUserAutomatedRepov DV2C ACIMINVACOnTOAskAnythingCont© AskJiminnyReporl© DealsV2Controlle:© OnDemandV2Con© PlaylistController.© PlaylistShareCont© ReportController.php© AutomatedReportsCommand.phpJiminnybeouecommana.ong= custom.log< console LUl= laravel.logA SF [jiminny@localhost]A HS_local [jiminny@localhost]A console [PROD]console SlAGiNG© AskJiminnyReportActivityService.php© ActivitySearch.php© AutomatedReportsSendCommand.php© AddLayoutEntities.php© Team.php© AutomatedReportsRepository.php X© AutomatedReportsService.phpC CreateHeldActivityEvent.phpOnDemandV2Controller.php x© HistoryService.php© FilterDefinitionCollection.php© Criteria.php© AskJiminnyReportActivityServiceTest.phpC) RequestGenerateAskJiminnyReportJobTest.phpclass OnDemandV2ControllerControllerJubede Tun gecaskany cnengnescoryneuuest sreuuest. osonnesponsel...s41 X2 ^(e) TrackProvidernstallled-vent.ono© CreateActivityLoggedEvent.php© UserPilotActivityListener.php(©) ActivityLogged.phpAutomatedReportsCallbackService.php© RequestGenerateAskJiminnyReportJob.phpRequestGenerateReportJob.php© AutomatedReportResult.php(C) AutomatedReport.php18457208209210211/*** Delete Ask Anything conversation history212 Ц >public function deleteAskAnythingHistory(Request $request): JsonResponsef...}258class Automacedкeрortskepo o:A15 M4 A VLOY/*** A5k Anything - subnit question and get nesponse61627677931141151161171181191211124123241 kg* Retrieve all standard (non-Ask Jiminny) m243244* @param string $sortColumnThe column to)245* dodron scrino osorcuurection ine sort culre246247* @return Collection<AutomatedReport>24824912 usagespublic function getAllStandardReports(string $sortColumn = 'created_at',string $sortDirection = 'desc'): Collection {...}250251252253254pubuie funetion askAnything (0noenandASkAnychängRequest Snequest): StreanesiResponsel USonRes/** @var User $user */$user = $request->user();nunus→> loodelything request received', I'user_id' => $user-›getId().'team_id' => $user->getTeamId(),'request_hash' => md5( string: $request->input( key: 'message') . $user->getId() . flor'message_preview' => mb_substr($request->input( key: 'message'), 0, 50),J):if ($featureCheck = $this->checkAskJiminnyOnAnythingFeature($user)) {return $featureCheck;/*** Retrieve all Ask Liminny reports createdtry {nunourvara = orequesteovauodtredr* Oodrdll usernusenIne user Ynos259* @param string $sortColumnThe column to* Oparam string $sortDirection The sort dire200262* @return Collection<AutomatedReport>263*/—26414 usages265public function getAskJiminnyReportsByUser(- 266User $user,267string $sortColumn = 'created_at',268string ssorcbirection = "desc"): Collection {...J$requestData = ['userQuestion' => $inputData[ 'message'],'callIds' => $this->historyService->getContextIds($user,identifier: HistoryServic'history' => $this->historyService->getHistory($user,identifier: HistoryService: :$teamAiContext = $this->teamAiContextRepository->getByTeamId($user->getTeamId()):if ($teamAiContext?->getPrompt() !== null) {srequescbacal ceamAlcontext'. = preamAlcontext->getrrompt;—271Z usages272private function buildSortedQuery(string $sor273/**-274* Get all active and enabled reports with al276277* @param string $frequency278— 279$this->historyService->appendToUserHistory($user,identifier: HistoryService::0N_DEMAND_SERVICE,$inputData[ 'message']):* dreturh coLcectzon<aucomacedкeрort>$this->historyService->appendToEventHistory(user: $user,identifier: HistoryService::0N_DEMAND_SERVICE,type: HIscoryservice..EVENI_IN_PRUGRESS_TYPEZ81123 usagespublic function getActiveReportsByFrequency(s)184283gctnoamPonloct = CtnoamPonloct •onfomandiii ovo (ineauoctlatan•Tests passed: 1 (2 minutes ago), 0lablf Support Daily • in 2h 49 mAAskJiminnyReportActivityServiceT…Defaults100% C•Tue 14 Apr 12:11:49CascadeFixing ReportControllerAutomated Report MarFixing Ask Jiminny Rep+D..Now let's run the test to verifvwtests/Unxt/Servsces/Kiosk/Automate/meports/AskJ1minnyreportActivätyserviceTest-php --no-coveragecould not open input Tile: /var/www/ncml/artisandockerdesks/nxe/ ervke /nosk/Autonape/aeport/ASkJiminnyReportActivityServiceTest.php --n-coverageCould not open input file: /app/artisarCommand dockerocker exec oocker land ioash —e"cd /var/www&& php artisan testLests unlu services Klosk Aucomaceakeporcs AskJiminnykeportAccivityservicelest.ono =-no-coverade D&l'Could not open input file: artisan• docker exec docker_lamp_1 bash -c "find / -name artisan -maxdepth 6 2>/dev/null | head -5"/home/jiminny/artisan"cd /homee/jiminny && php artisan testtests/nxt/sdrvicrs/K2psk/Autonat e"Reports/A3kiminnyReportActivatyserviceTest.php --no-coverage 2261PASSgetTests\Unit\Services\Kiosk\AutomatedReports\AskJiminnyReportActivityServiceTesta fittersemoty when no resultsE tatt tnt hperiod date filtersids bassess snazer fsequence number to disable first _ 0.025All 8 tests pass. Here's a summary:Root Cause & FixRoot cause: buildRequestParamsFromSearch never set sequence number in the request params, so Criteria::createFromRequest defaulted it to 0Since isFirstRequest() returns true when sequenceNumber === 0, several implicit defaults were silently applied:Activitvourat ionRande → min duration = 1 ilters ouf o-second activitiesiActivityRecorded → only_recorded = 1 (restricts to recorded activities only)OrganiserGroupIn → applies user's default group as a filtelThe frontend URL you noticed uses sequence_number=4, which disables these defaults - explaining why the frontend returned activities but the servicereturee o.Fix: AskJiminnyReportActivityService.php:51—added 'sequence_number' » 1 to the Criteria::createFromRequest merge, ensuring isFirstRequest() returns false and no implicit defaults are injected.Test added: testGetAct:1cylasPassesNonzerosequencenumberloDisablerarsckequestberaulus assers that the captured uriteria ob ect nas 1srirstRequest() === false.Öul ..Vew allliItlle wiun changesvapp/Services/Kiosk/AutomatedReports/D AskJiminnyReportActivityService.php +1 -1Reject allAccept allExplain it to me again. Why is there issue with that? Where is it expected and wy do l need to fork with that. How is it used in+ <> Code Claude Sonnet 4.6Winasun leams202:00uir-o( 4 spaces...
|
NULL
|
NULL
|
NULL
|
11084
|
|
11083
|
+SlackEDHomeDMSActivityFilesLater..•More+FileEditV +SlackEDHomeDMSActivityFilesLater..•More+FileEditViewGoHistoryWindowHelpJiminny ...# Starredplatform-inner-teamChannels# ai-chapter# alerts# backend# confusion-clinic# curiosity_lab# engineering# frontend# general# infra-changes# jiminny-bg# platform-tickets# product_launches# random# releases# sofia-office# support# thank-yous# the_people_of jimi…..Direct messagesAneliya Angelova, ...Steliyan GeorgievAdelina Petrova, Ili.... Adelina PetrovaO. Calea Dimitravo→Search Jiminny IncAneliya Angelova, Nikolay Yankov, Steliyan GeorgievMessagesAdd canvas+Nikolay Yankov 10:45 AMпиши кат оя рьннешLukas Kovalik 10:52 AMзабавих се че ми се разбазикаха settings за средипуснах и мина и fail-наима result но e failedзначиREASON_NOT_ENOUGH_ACTIVITIESвиж дали има нещо в OD със този филтьрNikolay Yankov 11:01 AMДобреNikolay Yankov 11:39 AMя рьнни пак LukasLukas Kovalik 11:43 AMготовосьщотоCompetitive pitches беше втория нали такаNikolay Yankov 12:04 PMДа, там има 14 активитита, защо не сработи този пьт?Lukas Kovalik 12:05 PMпак изглежда sequenceгледам гоMessage Aneliya Angelova, Nikolay Yankov, Steliyan Georgiev+Aalal]Support Daily - in 2h 49 m100% <47Tue 14 Apr 12:11:498Today ~...
|
NULL
|
NULL
|
NULL
|
11083
|
|
11082
|
PhpStormFileFV faVsco.js vProject vEditViewNavigat PhpStormFileFV faVsco.js vProject vEditViewNavigateCodeLaravelRefactor#11894 on JY-18909-automated-reports-ask-iminny K vToolsWindowHelp© JiminnyDebugCommanc© JiminnySetEncryptedTo© JiminnyTokenInfoComm© MakeSlackLivecoaching© Managescim-orleam.p(c Malkoanchrorenvironn© MuteOrganizerChannel.© PhpApm.php© PropagateCoachingFeer© PurgeConferences.php© PurgeSoftDeletedOppor© PurgeSyncBatchesComi© RecalculateDealRisksCa© RemoveDeleteMarkersC© RemoveExpiredNudgesi© RemoveUnusedParticip:© ResetElasticSearch.php© RestoreActivityCrmProv© RestoreActivityTypeCor© SeedActivities.php© SyncActivity.php©Tracklmported.php© UpdateActivitiesAverag© WhichWorkerlsWorkingr> Scheduling© Kernel.phpM Contracts> M Domain> MDTO> M Emails› _ Enums> D Events> D Exceptions> DJ FFMpeg>D Formats› D Guards› C Helpersv UHttp> MAccessTokenProviderv @ ControllersV DAPI> DAiCallScoringAiReports> D Deallnsights> D Opportunity> C Page> • ScorecardsSettingsTeamInsightsnemes> MUserAutomatedRepov DV2C ACIMINVACOnTOAskAnythingCont© AskJiminnyReporl© DealsV2Controlle:© OnDemandV2Con© PlaylistController.© PlaylistShareContTests passed: 1 (2 minutes ago)© ReportController.php© AutomatedReportsCommand.phpJiminnybeouecommana.ong= custom.log< console EUi= laravel.logA SF [jiminny@localhost]A HS_local [jiminny@localhost]A console [PROD]console SlAGiNG© AskJiminnyReportActivityService.php© ActivitySearch.php© AutomatedReportsSendCommand.php© AddLayoutEntities.php© Team.php© AutomatedReportsRepository.php X© AutomatedReportsService.phpCrealenelaAcuviyevent.ono(e TrackProvidernstallled-vent.onoOnDemandV2Controller.php© FilterDefinitionCollection.php© Criteria.php© AskJiminnyReportActivityServiceTest.phpcPequectcenerateask.iminnvreoorJoolestongclass OnDemandV2Controller extends ControllerA1 X2 лpublic function askAnything(OnDemandAskAnythingRequest $request): StreamedResponse|JsonResp=nrequest-ousero.© CreateActivityLoggedEvent.php© UserPilotActivityListener.php• ActivityLogged.phpAutomatedReportsCallbackService.phpC RequestGenerateAskJiminnyReportJob.phpRequestGenerateReportJob.php© AutomatedReportResult.php(C) AutomatedReport.phpclass Automacedкeрortskepo o:A15 X4 A v 2522411244245246247248249250251253254616275931141151161171181191211124123/*** Retrieve all standard (non-ASk Limiony) e256* @param string $sortColumnThe column t 258* @param string $sortDirection The sort dire259260$requestData = [* @return Collection<AutomatedReport>'userQuestion' => $inputData[ 'message'],*/262'callIds' => $this->historyService->getContextIds($user,identifer: HistoryServic12 usages263'history' = $this->historyService->getHistory(Suserdidentifier: HistoryService:public function getAllStandardReports(264]:265string $sortColumn = 'created_at',string $sortDirection = 'desc'266): Collection {..+267268фteamAlcontext = schis->ceamAlconcexckeposicory-›getbyleamta(puser->getleamta:if ($teamAiContext?->getPrompt( !== null) {$requestData['teamAiContext'] = $teamAiContext->getPrompt();/**269* Retrieve all Ask Liminny reports created* Oodrdll usernusenIne user Ynos272* @param string $sortColumnThe column t,273* Oparam string $sortDirection The sort dire274275276* @return Collection<AutomatedReport>277*/-27814 usagespublic function getAskJiminnyReportsByUser(User $user,string $sortColumn = 'created_at',string ssorcbirection = "desc"): Collection {...J282283— 285Z usagesprivate function buildSortedQuery(string $sor286- 288/*** Get all active and enabled reports with ac 289291* @param string $frequency292-293* dreturn cocLectron<Aucomacedкeрort»29423 usages295public function getActiveReportsByFrequency(s296297$this->logger->info('AskAnything request received', ['user_id' => $user-›getId(),'team_id' => $user->getTeamId(),'request_hash' => md5( string: $request->input( key: 'message') .$user->getId() . flor'message_preview' →> mb_substr($request->input( key: 'message'), 0, 50),I);if ($featureCheck = $this->checkAskJiminnyOnAnythingFeature($user)) €return steacureuneckitry &$inputData = $request->validated():$this->historyService->appendToUserHistory($user,identifier: HistoryService::0N_DEMAND_SERVICE,$inputData[ 'message']):$this->historyService->appendToEventHistory(user: $user,oenmer. scorvoeru Cer.UN UEMAND OCKuILCtype: HistoryService::EVENT_IN_PROGRESS_TYPE):$streamRequest = StreamRequest: :onDemondLevel($requestData);// Track active stream in Redis$this->activeStreamsRepository->start($user->getId(),$streamRequest->getId(),ruseconos. screankedves-›cerconnectmeour + screankequest-›cetreadiameoureturn $this->prophetService->getStreamed0rAbortedResponse(streamRequest: $streamRequest,onCompleted: function (string $assistantResponse,bool $clientAborted,, 0lablf Support Daily • in 2h 49 mAAskJiminnyReportActivityServiceT…Defaults100% C•Tue 14 Apr 12:11:37CascadeFixing ReportControllerAutomated Report MarFixing Ask Jiminny Rep+D..Now let's run the test to verifvwtests/Unxt/Servsces/Kiosk/Automate/meports/AskJ1minnyreportActivätyserviceTest-php --no-coverageloul nor oen ndlr Tler var wi nunbarusanCommand dockeldoster nxe ceockes /kJosk/AuP /ape/a/poras/A5kJ1minyReportActivityServiceTest.php --no-coverageCould not open input file: /app/artisanCommand dockerocker exec oocker land 1oash -d"cd /var/www&& php artisan testLests unlu services Klosk Aucomaceakeporcs AskJiminnykeportAccivityservicelest.ono =-no-coverade D&l'Could not open input file: artisan• docker exec docker_lamp_1 bash -c "find / -name artisan -maxdepth 6 2>/dev/null | head -5"/home/jiminny/artisan"cd /homee/jiminny && php artisan testtests nxe erckee/Kio5/AutonateReports/5KJimamyReportActivaty ServiceTest,php --no-coverage 261"PASSTests\Unit\Services\Kiosk\AutomatedReports\AskJiminnyReportActivityServiceTesta fittersemoty when no resultsE tatt tnt hperiod date filtersget activity ids hassees sn zero sequence number to disable first r._ 0.025All 8 tests pass. Here's a summary:Root Cause & FixKoOL cause: bu1 Ldkequestraramst romsearch never set sequence number In the request params, so criterla::creater romkequest delaulted lt to 0Since isFirstRequest() returns true when sequenceNumber === 0, several implicit defaults were silently applied:Activitvourat ionRande → min duration = 1 Tilters ouf o-second activitiesiActivityRecorded → only_recorded = 1 (restricts to recorded activities only)OrganiserGroupIn → applies user's default group as a filtelThe frontend URL you noticed uses sequence_number=4, which disables these defaults - explaining why the frontend returned activities but the servicereturee o.Fix: AskJiminnyReportActivityService.php:51—added 'sequence_number' » 1 to the Criteria::createFromRequest merge, ensuring isFirstRequest() returns false and no implicit defaults are injected.lest added: testbetacc1cylasPassesNonzerosequencenumberloDisablerarsckequestberaulus assers that the captured uriteria ob ect nas 1srirstRequest() === false.Öul ..Vew allliItlle wiun changesvapp/Services/Kiosk/AutomatedReports/D AskJiminnyReportActivityService.php +1 -1Reject allAccept allExplain it to me again. Why is there issue with that? Where is it expected and wy do l need to fork with that. How is it used in+ <> CodeClaude Sonnet 4.6winasun leams203:0uir-o( 4 spaces...
|
NULL
|
NULL
|
NULL
|
11082
|
|
11081
|
+SlackEDHomeDMSActivityFilesLater..•More+FileEditV +SlackEDHomeDMSActivityFilesLater..•More+FileEditViewGoHistoryWindowHelpJiminny ...# Starredplatform-inner-teamChannels# ai-chapter# alerts# backend# confusion-clinic# curiosity_lab# engineering# frontend# general# infra-changes# jiminny-bg# platform-tickets# product_launches# random# releases# sofia-office# support# thank-yous# the_people_of jimi…..Direct messagesAneliya Angelova, ...Steliyan GeorgievAdelina Petrova, Ili.... Adelina PetrovaO. Calea Dimitravo→Search Jiminny IncAneliya Angelova, Nikolay Yankov, Steliyan GeorgievMessagesAdd canvas+Nikolay Yankov 10:45 AMпиши кат оя рьннешLukas Kovalik 10:52 AMзабавих се че ми се разбазикаха settings за средипуснах и мина и fail-наима result но e failedзначиREASON_NOT_ENOUGH_ACTIVITIESвиж дали има нещо в OD със този филтьрNikolay Yankov 11:01 AMДобреNikolay Yankov 11:39 AMя рьнни пак LukasLukas Kovalik 11:43 AMготовосьщотоCompetitive pitches беше втория нали такаNikolay Yankov 12:04 PMДа, там има 14 активитита, защо не сработи този пьт?Lukas Kovalik 12:05 PMпак изглежда sequenceгледам гоMessage Aneliya Angelova, Nikolay Yankov, Steliyan Georgiev+Aalal]Support Daily - in 2h 49 m100% <47Tue 14 Apr 12:11:378Today ~...
|
NULL
|
NULL
|
NULL
|
11081
|
|
11080
|
+SlackEDHomeDMSActivityFilesLater..•More+FileEditV +SlackEDHomeDMSActivityFilesLater..•More+FileEditViewGoHistoryWindowHelpJiminny ...# Starredplatform-inner-teamChannels# ai-chapter# alerts# backend# confusion-clinic# curiosity_lab# engineering# frontend# general# infra-changes# jiminny-bg# platform-tickets# product launches# random# releases# sofia-office# support# thank-yous# the_people_of jimi…..Direct messagesAneliya Angelova, ...Steliyan GeorgievAdelina Petrova, Ili.... Adelina PetrovaO. Calea Dimitravo→Search Jiminny IncAneliya Angelova, Nikolay Yankov, Steliyan GeorgievMessagesAdd canvas+Nikolay Yankov 10:45 AMпиши кат оя рьннешLukas Kovalik 10:52 AMзабавих се че ми се разбазикаха settings за средипуснах и мина и fail-наима result но e failedзначиREASON_NOT_ENOUGH_ACTIVITIESвиж дали има нещо в OD със този филтьрNikolay Yankov 11:01 AMДобреNikolay Yankov 11:39 AMя рьнни пак LukasLukas Kovalik 11:43 AMготовосьщотоCompetitive pitches беше втория нали такаNikolay Yankov 12:04 PMДа, там има 14 активитита, защо не сработи този пьт?Lukas Kovalik 12:05 PMпак изглежда sequenceгледам гоMessage Aneliya Angelova, Nikolay Yankov, Steliyan Georgiev+Aalal]Support Daily - in 2h 49 m100% <47Tue 14 Apr 12:11:358Today ~...
|
NULL
|
NULL
|
NULL
|
11080
|
|
11079
|
PhpStormFileFV faVsco.js vProject vEditViewNavigat PhpStormFileFV faVsco.js vProject vEditViewNavigateCodeLaravelRefactor#11894 on JY-18909-automated-reports-ask-iminny K vToolsWindowHelp© JiminnyDebugCommanc© JiminnySetEncryptedTo© JiminnyTokenInfoComm© MakeSlackLivecoaching© Managescim-orleam.p(c Malkoanchrocnvronnl© MuteOrganizerChannel.© PhpApm.php© PropagateCoachingFeer© PurgeConferences.php© PurgeSoftDeletedOppor© PurgeSyncBatchesComiC RecalculateDealRisksCa© RemoveDeleteMarkersC© RemoveExpiredNudgesi© RemoveUnusedParticip:© ResetElasticSearch.php© RestoreActivityCrmProv© RestoreActivityTypeCor© SeedActivities.php© SyncActivity.php©Tracklmported.php© UpdateActivitiesAverag© WhichWorkerlsWorkingr> Scheduling© Kernel.phpM Contracts> M Domain> MDTO> M Emails› _ Enums> D Events> D Exceptions> DJ FFMpeg>D Formats› D Guards› C Helpersv UHttp> MAccessTokenProviderv @ ControllersV DAPI> DAiCallScoringAiReports> D Deallnsights> D Opportunity> C Page> • ScorecardsSettingsTeamInsightsnemes> MUserAutomatedRepov DV2C ACIMINVACOnTOAskAnythingCont© AskJiminnyReporl© DealsV2Controlle:© OnDemandV2Con© PlaylistController.© PlaylistShareCont© ReportController.php© AutomatedReportsCommand.phpJiminnybeouecommana.ong= custom.log< console EUi= laravel.logA SF [jiminny@localhost]A HS_local [jiminny@localhost]A console [PROD]console SlAGiNG© AskJiminnyReportActivityService.php© ActivitySearch.php© AutomatedReportsSendCommand.php© AddLayoutEntities.php© Team.php© AutomatedReportsRepository.php X© AutomatedReportsService.phpCrealenelaAcuviyevent.ono(e) TrackProvidernstallled-vent.onoOnDemandV2Controller.php >© FilterDefinitionCollection.php© Criteria.php© AskJiminnyReportActivityServiceTest.phpcPequectcenerateask.iminnvreoorJoolestongclass OnDemandV2Controller extends ControllerA1 X2 лpublic function askAnything(OnDemandAskAnythingRequest $request): StreamedResponse|JsonResp=nrequest-ousero.© CreateActivityLoggedEvent.php© UserPilotActivityListener.php• ActivityLogged.phpAutomatedReportsCallbackService.phpC RequestGenerateAskJiminnyReportJob.phpRequestGenerateReportJob.php© AutomatedReportResult.php(C) AutomatedReport.phpclass Automacedкeрortskepo o:A15 X4 A v 2522411244245246247248249250251253254616275931141151161171181191211124123/*** Retrieve all standard (non-ASk Limiony) e256* @param string $sortColumnThe column t 258* @param string $sortDirection The sort dire259260$requestData = [* @return Collection<AutomatedReport>'userQuestion' => $inputData[ 'message'],*/262'callIds' => $this->historyService->getContextIds($user,identifer: HistoryServic12 usages263identifier: HistoryService:public function getAllStandardReports(264]:'history' => $this->historyService->getHistory($user,265string $sortColumn = 'created_at',string $sortDirection = 'desc'266): Collection {..+267268фteamAlcontext = schis->ceamAlconcexckeposicory-›getbyleamta(puser-›getleamta:if ($teamAiContext?->getPrompt( !== null) {$requestData['teamAiContext'] = $teamAiContext->getPrompt();/**269* Retrieve all Ask Liminny reports created* Oodrdll usernusenIne user Ynos272* @param string $sortColumnThe column t,273* Oparam string $sortDirection The sort dire274275* @return Collection<AutomatedReport>276277*/- 27814 usagespublic function getAskJiminnyReportsByUser(User $user,string $sortColumn = 'created_at',string ssorcbirection = "desc"): Collection {...J281282283284— 285Z usagesprivate function buildSortedQuery(string $sor286- 288/*** Get all active and enabled reports with ac 289291* @param string $frequency292-293* dreturh coLcectzon<aucomacedкeрort>29423 usages295public function getActiveReportsByFrequency(s296297$this->logger->info('AskAnything request received', ['user_id' => $user-›getId(),'team_id' => $user->getTeamId(),'request_hash' => md5( string: $request->input( key: 'message') .$user->getId() . flor'message_preview' →> mb_substr($request->input( key: 'message'), 0, 50),I);if ($featureCheck = $this->checkAskJiminnyOnAnythingFeature($user)) €return steacureuneckitry &$inputData = $request->validated():$this->historyService->appendToUserHistory($user,identifier: HistoryService::0N_DEMAND_SERVICE,$inputData[ 'message']):$this->historyService->appendToEventHistory(user: $user,identifier: HistoryService::ON_DEMAND_SERVICE,type: HistoryService::EVENT_IN_PROGRESS_TYPE):$streamRequest = StreamRequest: :onDemandLevel($requestData);// Track active stream in Redis$this->activeStreamsRepository->start($user->getId(),$streamRequest->getId(),ruseconos. screankedves-›cerconnectmeour + screankequest-›cetreadiameou):return $this->prophetService->getStreamed0rAbortedResponse(streamRequest: $streamRequest,onCompleted: function (string $assistantResponse,bool $clientAborted,Tests passed: 1 (2 minutes ago), 0lablf Support Daily • in 2h 49 mAAskJiminnyReportActivityServiceT…Defaults100% C•Tue 14 Apr 12:11:34CascadeFixing ReportControllerAutomated Report MarFixing Ask Jiminny Rep+D..Now let's run the test to verifvwtests/Unxt/Servsces/Kiosk/Automate/meports/AskJ1minnyreportActivätyserviceTest-php --no-coverageloul nor oen tndlr Tler var ww nunwarusanCommand dockeldoster nxe ceockes /kJosk/AuP /ape/a/poras/A5kJ1minyReportActivityServiceTest.php --no-coverageCould not open input file: /app/artisanCommand dockerocker exec oocker land 1oash -d"cd /var/www&& php artisan testLests unlu services Klosk Aucomaceakeporcs AskJiminnykeportAccivityservicelest.ono =-no-coverade D&l'Could not open input file: artisan• docker exec docker lamp 1 bash -c "find / -name artisan -maxdenth 6 2>/dev/null | head -5"/home/jiminny/artisan"cd /homee/jiminny && php artisan testtests/nxe erckee/Kio5/AutonateReports/5KJimamyReportActivaty ServiceTest, php --no-coverage 2561"PASSTests\Unit\Services\Kiosk\AutomatedReports\AskJiminnyReportActivityServiceTestemoty when no resultsE tatt tnt hperiod date filtershand lesids bassess snazer fsequence number to disable first _ 0.025All 8 tests pass. Here's a summary:Root Cause & FixKoOL cause: bu1 Ldkequestraramst romsearch never set sequence number In the request params, so criterla::creater romkequest delaulted lt to 0Since isFirstRequest() returns true when sequenceNumber === 0, several implicit defaults were silently applied:Activitvourat ionRande → min duration = 1 Tilters ouf o-second activitiesiActivityRecorded → only_recorded = 1 (restricts to recorded activities only)OrganiserGroupin → apolies user's derault croup as a tiltelThe frontend URL you noticed uses sequence_number=4, which disables these defaults - explaining why the frontend returned activities but the servicereturee o.Fix: AskJiminnyReportActivityService.php:51—added 'sequence_number' → 1 to the Criteria: : createFromRequest merge, ensuring isFirstRequest() returns false and no implicit defaults are injected.lest added: testbetaccLeylasPassesNonzerosequencenumberloD1sablerirsckequestberauuus asserts that the captured uriteria ob ect nas 1srirstRequest() === false.Öul ..Vew allliItlle wiun changesvapp/Services/Kiosk/AutomatedReports/D AskJiminnyReportActivityService.php +1 -1Reject allAccept allExplain it to me again. Why is there issue with that? Where is it expected and wy do l need to fork with that. How is it used in+ <> CodeClaude Sonnet 4.6Winasun leams292:0/uir-o( 4 spaces...
|
NULL
|
NULL
|
NULL
|
11079
|
|
11078
|
+SlackEDHomeDMSActivityFilesLater..•More+FileEditV +SlackEDHomeDMSActivityFilesLater..•More+FileEditViewGoHistoryWindowHelpJiminny ...# Starredplatform-inner-teamChannels# ai-chapter# alerts# backend# confusion-clinic# curiosity_lab# engineering# frontend# general# infra-changes# jiminny-bg# platform-tickets# product launches# random# releases# sofia-office# support# thank-yous# the_people_of jimi…..Direct messagesAneliya Angelova, ...Steliyan GeorgievAdelina Petrova, Ili.... Adelina PetrovaO. Calea Dimitravo→Search Jiminny IncAneliya Angelova, Nikolay Yankov, Steliyan GeorgievMessagesAdd canvas+Nikolay Yankov 10:45 AMпиши кат оя рьннешLukas Kovalik 10:52 AMзабавих се че ми се разбазикаха settings за средипуснах и мина и fail-наима result но e failedзначиREASON_NOT_ENOUGH_ACTIVITIESвиж дали има нещо в OD със този филтьрNikolay Yankov 11:01 AMДобреNikolay Yankov 11:39 AMя рьнни пак LukasLukas Kovalik 11:43 AMготовосьщотоCompetitive pitches беше втория нали такаNikolay Yankov 12:04 PMДа, там има 14 активитита, защо не сработи този пьт?Lukas Kovalik 12:05 PMпак изглежда sequenceгледам гоMessage Aneliya Angelova, Nikolay Yankov, Steliyan Georgiev+Aalal]Support Daily - in 2h 49 m100% <47Tue 14 Apr 12:11:348Today ~...
|
NULL
|
NULL
|
NULL
|
11078
|
|
11077
|
+SlackEDHomeDMSActivityFilesLater..•More+FileEditV +SlackEDHomeDMSActivityFilesLater..•More+FileEditViewGoHistoryWindowHelpJiminny ...# Starredplatform-inner-teamChannels# ai-chapter# alerts# backend# confusion-clinic# curiosity_lab# engineering# frontend# general# infra-changes# jiminny-bg# platform-tickets# product_launches# random# releases# sofia-office# support# thank-yous# the_people_of jimi…..Direct messagesAneliya Angelova, ...Steliyan GeorgievAdelina Petrova, Ili.... Adelina PetrovaO. Calea Dimitravo→Search Jiminny IncAneliya Angelova, Nikolay Yankov, Steliyan GeorgievMessagesAdd canvas+Nikolay Yankov 10:45 AMпиши кат оя рьннешLukas Kovalik 10:52 AMзабавих се че ми се разбазикаха settings за средипуснах и мина и fail-наима result но e failedзначиREASON_NOT_ENOUGH_ACTIVITIESвиж дали има нещо в OD със този филтьрNikolay Yankov 11:01 AMДобреNikolay Yankov 11:39 AMя рьнни пак LukasLukas Kovalik 11:43 AMготовосьщотоCompetitive pitches беше втория нали такаNikolay Yankov 12:04 PMДа, там има 14 активитита, защо не сработи този пьт?Lukas Kovalik 12:05 PMпак изглежда sequenceгледам гоMessage Aneliya Angelova, Nikolay Yankov, Steliyan Georgiev+Aalal]Support Daily - in 2h 49 m100% <47Tue 14 Apr 12:11:328Today ~...
|
NULL
|
NULL
|
NULL
|
11077
|
|
11076
|
PhpStormFileFV faVsco.js vProject vEditViewNavigat PhpStormFileFV faVsco.js vProject vEditViewNavigateCodeLaravelRefactor#11894 on JY-18909-automated-reports-ask-iminny K vToolsWindowHelp© JiminnyDebugCommanc© JiminnySetEncryptedTo© JiminnyTokenInfoComm© MakeSlackLivecoaching© Managescim-orleam.p(c Malkoanchrocnvronnl© MuteOrganizerChannel.© PhpApm.php© PropagateCoachingFeer© PurgeConferences.php© PurgeSoftDeletedOppor© PurgeSyncBatchesComiC RecalculateDealRisksCa© RemoveDeleteMarkersC© RemoveExpiredNudgesi© RemoveUnusedParticip:© ResetElasticSearch.php© RestoreActivityCrmProv© RestoreActivityTypeCor© SeedActivities.php© SyncActivity.php©Tracklmported.php© UpdateActivitiesAverag© WhichWorkerlsWorkingr> Scheduling© Kernel.phpM Contracts> M Domain> MDTO> M Emails› _ Enums> D Events> D Exceptions> DJ FFMpeg>D Formats› D Guards› C Helpersv UHttp> MAccessTokenProviderv @ ControllersV DAPI> D AiCallScoringAiReports> D Deallnsights> D Opportunity> C Page> • ScorecardsSettingsTeamInsightsnemes> MUserAutomatedRepov DV2C ACIMINVACONTOAskAnythingCont© AskJiminnyReporl© DealsV2Controlle:© OnDemandV2Con© PlaylistController.© PlaylistShareCont© ReportController.phpC AutomatedReportsCommand.phpJiminnybeouecommana.ong= custom.log< console EUi= laravel.logA SF [jiminny@localhost]A HS_local [jiminny@localhost]console SlAGiNG© AskJiminnyReportActivityService.phpA console [PROD]© ActivitySearch.php© AutomatedReportsSendCommand.php© AddLayoutEntities.php© Team.php© AutomatedReportsRepository.php X© AutomatedReportsService.phpCrealenelaAcuviyevent.ono(e) TrackProvidernstallled-vent.onoOnDemandV2Controller.php >© FilterDefinitionCollection.php© Criteria.php© AskJiminnyReportActivityServiceTest.phpcPequectcenerateask.iminnvreoorJoolestongclass OnDemandV2Controller extends ControllerA1 X2 лpublic function askAnything(OnDemandAskAnythingRequest $request): StreamedResponse |JsonResp=nrequest-ousero.© CreateActivityLoggedEvent.php© UserPilotActivityListener.php• ActivityLogged.phpAutomatedReportsCallbackService.phpC RequestGenerateAskJiminnyReportJob.phpRequestGenerateReportJob.php© AutomatedReportResult.php(C) AutomatedReport.phpclass Automacedкeрortskepo o:A15 X4 A v 2522411244245246247248249250251253254616275931141151161171181191211124123/*** Retrieve all standard (non-ASk Limiony) e256* @param string $sortColumnThe column t 258* @param string $sortDirection The sort dire259260$requestData = [* @return Collection<AutomatedReport>'userQuestion' => $inputData[ 'message'],*/262'callIds' => $this->historyService->getContextIds($user,identifier: HistoryServic12 usages263identifier: HistoryService:public function getAllStandardReports(264]:'history' => $this->historyService->getHistory($user,265string $sortColumn = 'created_at',string $sortDirection = 'desc'266): Collection {..+267268фteamAlcontext = schis->ceamAlconcexckeposicory-›getbyleamta(puser->getleamta:if ($teamAiContext?->getPrompt( !== null) {$requestData['teamAiContext'] = $teamAiContext->getPrompt();/**269* Retrieve all Ask Liminny reports created* Oodrdll usernusenIne user Ynos272* @param string $sortColumnThe column t,273* Oparam string $sortDirection The sort dire274275276* @return Collection<AutomatedReport>277*/-27814 usagespublic function getAskJiminnyReportsByUser(User $user,string $sortColumn = 'created_at',string ssorcbirection = "desc"): Collection {...J282283— 285Z usagesprivate function buildSortedQuery(string $sor286- 288/*** Get all active and enabled reports with ac 289291* @param string $frequency292-293* dreturh coLcectzon<aucomacedкeрort>29423 usages295public function getActiveReportsByFrequency(s296297$this->logger->info('AskAnything request received', ['user_id' => $user-›getId(),'team_id' => $user->getTeamId(),'request_hash' => md5( string: $request->input( key: 'message') .$user->getId() . flor'message_preview' →> mb_substr($request->input( key: 'message'), 0, 50),I);if ($featureCheck = $this->checkAskJiminnyOnAnythingFeature($user)) €return steacureuneckitry &$inputData = $request->validated():$this->historyService->appendToUserHistory($user,identifier: HistoryService::0N_DEMAND_SERVICE,$inputData[ 'message']$this->historyService->appendToEventHistory(user: $user,identifien: HistoryService: :ON_DEPAND_SERVICE,type: HistoryService::EVENT_IN_PROGRESS_TYPE):$streamRequest = StreamRequest: :onDemandLevel($requestData);// Track active stream in Redis$this->activeStreamsRepository->start($user->getId(),$streamRequest->getId(),ruseconos. screankedves-›cerconnectmeour + screankequest-›cetreadiameoureturn $this->prophetService->getStreamed0rAbortedResponse(streamRequest: $streamRequest,onCompleted: function (string $assistantResponse,bool $clientAborted,Tests passed: 1 (2 minutes ago), 0lablf Support Daily • in 2h 49 mAAskJiminnyReportActivityServiceT…Defaults100% C•Tue 14 Apr 12:11:31CascadeFixing ReportControllerAutomated Report MarFixing Ask Jiminny Rep+D..Now let's run the test to verifvwtests/Unxt/Servsces/Kiosk/Automate/meports/AskJ1minnyreportActivätyserviceTest-php --no-coverageloul nor oen ndlr Tler var wi nunbarusanCommand dockeldoster nxe ceockes /kJosk/AuP /ape/a/poras/A5kJ1minyReportActivityServiceTest.php --no-coverageCould not open input file: /app/artisanCommand dockerocker exec oocker lano oasn —"cd /var/www&& php artisan testLests unlu services Klosk Aucomaceakeporcs AskJiminnykeportAccivityservicelest.ono =-no-coverade D&l'Could not open input file: artisan• docker exec docker_lamp_1 bash -c "find / -name artisan -maxdepth 6 2>/dev/null | head -5"/home/jiminny/artisan"cd /homee/jiminny && php artisan testtests/nxe erckee/Kio5/AutonateReports/5KJimamyReportActivaty ServiceTest, php --no-coverage 2561"PASSTests\Unit\Services\Kiosk\AutomatedReports\AskJiminnyReportActivityServiceTesta fittersemoty when no resultsE tatt tnt hperiod date filtersids bassess snazero fsequence number to disable first ._. 0.025All 8 tests pass. Here's a summary:Root Cause & FixKoOL cause: bu1 Ldkequestraramst romsearch never set sequence number In the request params, so criterla::creater romkequest delaulted lt to 0Since isFirstRequest() returns true when sequenceNumber === 0, several implicit defaults were silently applied:Activitvourat ionRande → min duration = 1 Tilters ouf o-second activitiesiActivityRecorded → only_recorded = 1 (restricts to recorded activities only)OrganiserGroupIn → applies user's default group as a filtelThe frontend URL you noticed uses sequence_number=4, which disables these defaults - explaining why the frontend returned activities but the servicereturee o.Fix: AskJiminnyReportActivityService.php:51—added 'sequence_number' » 1 to the Criteria::createFromRequest merge, ensuring isFirstRequest() returns false and no implicit defaults are injected.lest added: testbetacc1cylasPassesNonzerosequencenumberloDisablerarsckequestberaulus assers that the captured uriteria ob ect nas 1srirstRequest() === false.Oul .Vew allliItlle wiun changesvapp/Services/Kiosk/AutomatedReports/D AskJiminnyReportActivityService.php +1 -1Reject allAccept allExplain it to me again. Why is there issue with that? Where is it expected and wy do l need to fork with that. How is it used in+ <> CodeClaude Sonnet 4.6Winasun leams203:05uir-o( 4 spaces...
|
NULL
|
NULL
|
NULL
|
11076
|
|
11075
|
+SlackEDHomeDMSActivityFilesLater..•More+FileEditV +SlackEDHomeDMSActivityFilesLater..•More+FileEditViewGoHistoryWindowHelpJiminny ...# Starredplatform-inner-teamChannels# ai-chapter# alerts# backend# confusion-clinic# curiosity_lab# engineering# frontend# general# infra-changes# jiminny-bg# platform-tickets# product_launches# random# releases# sofia-office# support# thank-yous# the_people_of jimi…..Direct messagesAneliya Angelova, ...Steliyan GeorgievAdelina Petrova, Ili.... Adelina PetrovaO. Calea Dimitravo→Search Jiminny IncAneliya Angelova, Nikolay Yankov, Steliyan GeorgievMessagesAdd canvas+Nikolay Yankov 10:45 AMпиши кат оя рьннешLukas Kovalik 10:52 AMзабавих се че ми се разбазикаха settings за средипуснах и мина и fail-наима result но e failedзначиREASON_NOT_ENOUGH_ACTIVITIESвиж дали има нещо в OD със този филтьрNikolay Yankov 11:01 AMДобреNikolay Yankov 11:39 AMя рьнни пак LukasLukas Kovalik 11:43 AMготовосьщотоCompetitive pitches беше втория нали такаNikolay Yankov 12:04 PMДа, там има 14 активитита, защо не сработи този пьт?Lukas Kovalik 12:05 PMпак изглежда sequenceгледам гоMessage Aneliya Angelova, Nikolay Yankov, Steliyan Georgiev+Aalal]Support Daily - in 2h 49 m100% <47Tue 14 Apr 12:11:3186 0Today ~...
|
NULL
|
NULL
|
NULL
|
11075
|
|
11074
|
PhpStormFileFV faVsco.js vProject vEditViewNavigat PhpStormFileFV faVsco.js vProject vEditViewNavigateCodeLaravelRefactor#11894 on JY-18909-automated-reports-ask-iminny k vToolsWindowHelp© JiminnyDebugCommanc© JiminnySetEncryptedTo© JiminnyTokenInfoComm© MakeSlackLivecoaching© Managescim-orleam.p(c Malkoanchrocnvronnl© MuteOrganizerChannel.© PhpApm.php© PropagateCoachingFeer© PurgeConferences.php© PurgeSoftDeletedOppor© PurgeSyncBatchesComiC RecalculateDealRisksCa© RemoveDeleteMarkersC© RemoveExpiredNudgesi© RemoveUnusedParticip:© ResetElasticSearch.php© RestoreActivityCrmProv© RestoreActivityTypeCor© SeedActivities.php© SyncActivity.php©Tracklmported.php© UpdateActivitiesAverag© WhichWorkerlsWorkingr> Scheduling© Kernel.phpM Contracts> M Domain> MDTO> M Emails› _ Enums> D Events> D Exceptions> DJ FFMpeg>D Formats› D Guards› C Helpersv UHttp> MAccessTokenProviderv @ ControllersV DAPI> D AiCallScoringAiReports> D Deallnsights> D Opportunity> C Page> • Scorecards> D SettingsTeamInsightsnemes> MUserAutomatedRepov DV2C ACIMINVACOnTOAskAnythingCont© AskJiminnyReporl© DealsV2Controlle:© OnDemandV2Con© PlaylistController.© PlaylistShareCont© ReportController.php© AutomatedReportsCommand.phpJiminnybeouecommana.ong= custom.log< console EUi= laravel.logA SF [jiminny@localhost]A HS_local [jiminny@localhost]A console [PROD]console SlAGiNG© AskJiminnyReportActivityService.php© ActivitySearch.php© AutomatedReportsSendCommand.php© AddLayoutEntities.php© Team.php© AutomatedReportsRepository.php X© AutomatedReportsService.phpCrealenelaAcuviyevent.ono(e TrackProvidernstallled-vent.onoOnDemandV2Controller.php >© FilterDefinitionCollection.php© Criteria.php© AskJiminnyReportActivityServiceTest.phpcPoquoctcenerateask.iminnvreoorJoolestongclass OnDemandV2Controller extends ControllerA1 X2 лpublic function askAnything(OnDemandAskAnythingRequest $request): StreamedResponse|JsonResp=nrequest-ousero.© CreateActivityLoggedEvent.php© UserPilotActivityListener.php• ActivityLogged.phpAutomatedReportsCallbackService.phpC RequestGenerateAskJiminnyReportJob.phpRequestGenerateReportJob.php© AutomatedReportResult.php(C) AutomatedReport.phpclass Automacedкeрortskepo o:A15 X4 A v 2522411244245246247248249250251253254616275931141151161171181191211124123/*** Retrieve all standard (non-Ask Limiony) e256* @param string $sortColumnThe column t 258* @param string $sortDirection The sort dire259260$requestData = [* @return Collection<AutomatedReport>*/262vstqus 3o Stms -Shistorya vase-sge teontexezds (suser,identifier: HistoryServic12 usages263identifier: HistoryService:public function getAllStandardReports(264]:'history' => $this->historyService->getHistory($user,265string $sortColumn = 'created_at',string $sortDirection = 'desc'266): Collection {..+267268фteamAlcontext = schis->ceamAlconcexckeposicory-›getbyleamta(puser->getleamtaiif ($teamAiContext?->getPrompt( !== null) {$requestData['teamAiContext'] = $teamAiContext->getPrompt();/**269* Retrieve all Ask Liminny reports created* Oodrdll usernusenIne user Ynos272* @param string $sortColumnThe column t,273* Oparam string $sortDirection The sort dire274275* @return Collection<AutomatedReport>276277*/- 27814 usagespublic function getAskJiminnyReportsByUser(User $user,string $sortColumn = 'created_at',string ssorcbirection = "desc"): Collection {...J282283284— 285Z usagesprivate function buildSortedQuery(string $sor286- 288/*** Get all active and enabled reports with ac 289291* @param string $frequency292-293* dreturn cocLectron<Aucomacedкeрort»29423 usages295public function getActiveReportsByFrequency(s296297$this->logger->info('AskAnything request received', ['user_id' => $user-›getId(),'team_id' => $user->getTeamId(),'request_hash' => md5( string: $request->input( key: 'message') .$user->getId() . flor'message_preview' →> mb_substr($request->input( key: 'message'), 0, 50),I);if ($featureCheck = $this->checkAskJiminnyOnAnythingFeature($user)) €return steacureuneckitry &$inputData = $request->validated():$this->historyService->appendToUserHistory($user,identifier: HistoryService::0N_DEMAND_SERVICE,$inputData[ 'message']nunus-onscorvservce-›aooeno o-venchistorvuuuser. nuseraoenmer. scorvoeru Cer.UN UEMAND OCKuILCtype: HistoryService::EVENT_IN_PROGRESS_TYPE):$streamRequest = StreamRequest: :onDemandLevel($requestData);// Track active stream in Redis$this->activeStreamsRepository->start($user->getId(),$streamRequest->getId(),tseconos: oscreankedves-›cerconnectmeour + screankequest-›cetreadimeoureturn $this->prophetService->getStreamed0rAbortedResponse(streamRequest: $streamRequest,onCompleted: function (string $assistantResponse,bool $clientAborted,Tests passed: 1 (2 minutes ago), 0lablf Support Daily • in 2h 49 mAAskJiminnyReportActivityServiceT…Defaults100% C•Tue 14 Apr 12:11:29CascadeFixing ReportControllerAutomated Report MarFixing Ask Jiminny Rep+D..Now let's run the test to verifywtests/Unxt/Servsces/Kiosk/Automate/meports/AskJ1minnyreportActivätyserviceTest-php --no-coverageloul nor oen ndlr Tler var wi nunbarusanCommand dockeldoster nxe ceockes /kJosk/AuP /ape/a/poras/A5kJ1minyReportActivityServiceTest.php --no-coverageCould not open input file: /app/artisanCommand dockeroocker exec oocker lano oasn —c"cd /var/www&& php artisan testLests unlu services Klosk Aucomaceakeporcs AskJiminnykeportAccivityservicelest.ono =-no-coverade D&l'Could not open input file: artisan• docker exec docker_lamp_1 bash -c "find / -name artisan -maxdepth 6 2>/dev/null | head -5"/home/jiminny/artisan"cd /homee/jiminny && php artisan testtests/nxe erckee/Kio5/AutonateReports/5KJimamyReportActivaty ServiceTest, php --no-coverage 2561"PASSTests\Unit\Services\Kiosk\AutomatedReports\AskJiminnyReportActivityServiceTestemoty when no resultsE tatt tnt hperiod date filtershand lesids bassess snazer fsequence number to disable first _ 0.025All 8 tests pass. Here's a summary:Root Cause & FixKoOL cause: bu1 Ldkequestraramst romsearch never set sequence number In the request params, so criterla::creater romkequest delaulted lt to 0Since isFirstRequest() returns true when sequenceNumber === 0, several implicit defaults were silently applied:Activitvourat ionRande → min duration = 1 Tilters ouf o-second activitiesiActivityRecorded → only_recorded = 1 (restricts to recorded activities only)OrganiserGroupin → apolies user's derault croup as a tiltelThe frontend URL you noticed uses sequence_number=4, which disables these defaults - explaining why the frontend returned activities but the servicereturee o.Fix: AskJiminnyReportActivityService.php:51—added 'sequence_number' » 1 to the Criteria::createFromRequest merge, ensuring isFirstRequest() returns false and no implicit defaults are injected.lest added: testbetacc1cylasPassesNonzerosequencenumberloDisablerarsckequestberaulus assers that the captured uriteria ob ect nas 1srirstRequest() === false.Öul ..Vew allliItlle wiun changesvapp/Services/Kiosk/AutomatedReports/D AskJiminnyReportActivityService.php +1 -1Reject allAccept allExplain it to me again. Why is there issue with that? Where is it expected and wy do l need to fork with that. How is it used in+ ‹> CodeClaude Sonnet 4.6W Windsurf Teams241:100uir-o( 4 spaces...
|
NULL
|
NULL
|
NULL
|
11074
|
|
11073
|
Project: faVsco.js, menu
#11894 on JY-18909-automa Project: faVsco.js, menu
#11894 on JY-18909-automated-reports-ask-jiminny, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceT…Defaults
Run 'AskJiminnyReportActivityServiceTest.tes…uenceNumberToDisableFirstRequestDefaults'
Debug 'AskJiminnyReportActivityServiceTest.tes…uenceNumberToDisableFirstRequestDefaults'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Sync Changes
Hide This Notification
Code changed:
Hide
1
2
Previous Highlighted Error
Next Highlighted Error
<?php
declare(strict_types=1);
namespace Jiminny\Http\Controllers\API\V2;
use Exception;
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Routing\Controller;
use Illuminate\Validation\ValidationException;
use Jiminny\Component\ActivitySearch\Service\ActivitySearch;
use Jiminny\Component\AskAnything\HistoryService;
use Jiminny\Component\AskJiminnyAi\Exceptions\AskJiminnyException;
use Jiminny\Component\AskJiminnyAi\OnDemandLevel\Events\AskAnythingAbortedChatCompleted;
use Jiminny\Component\Prophet\ProphetService;
use Jiminny\Component\ProphetAi\StreamRequest;
use Jiminny\Events\EventDispatcher;
use Jiminny\Exceptions\ActivityProviderException;
use Jiminny\Http\Requests\API\V2\OnDemandAskAnythingRequest;
use Jiminny\Models\Feature\FeatureEnum;
use Jiminny\Models\User;
use Jiminny\Repositories\ActiveStreamsRepository;
use Jiminny\Repositories\ElasticActivityRepository;
use Jiminny\Repositories\TeamAiContextRepository;
use Jiminny\Utils\FilterNormalizer;
use Jiminny\VO;
use Psr\Log\LoggerInterface;
use Symfony\Component\HttpFoundation\Response as ResponseAlias;
use Symfony\Component\HttpFoundation\StreamedResponse;
class OnDemandV2Controller extends Controller
{
use AuthorizesRequests;
private const int DEFAULT_TOP_ACTIVITIES_COUNT = 100;
private const array FILTER_KEY_EXCLUDED_PARAMS = [
'sequence_number',
'page',
'per_page',
'limit',
'offset',
];
public function __construct(
private readonly ActivitySearch $activitySearch,
private readonly HistoryService $historyService,
private readonly ProphetService $prophetService,
private readonly TeamAiContextRepository $teamAiContextRepository,
private readonly ActiveStreamsRepository $activeStreamsRepository,
private readonly EventDispatcher $eventDispatcher,
private readonly LoggerInterface $logger,
) {
}
/**
* Check if the user's team has the ASK_JIMINNY_ON_ANYTHING feature enabled
*/
private function checkAskJiminnyOnAnythingFeature(User $user): ?JsonResponse
{
if (! $user->team->hasFeature(FeatureEnum::ASK_JIMINNY_ON_ANYTHING)) {
return new JsonResponse([
'message' => 'Feature ASK_JIMINNY_ON_ANYTHING is not enabled for this team',
], ResponseAlias::HTTP_FORBIDDEN);
}
return null;
}
/**
* Get top N activity IDs for Ask Jiminny feature based on filters
*
* @throws ValidationException
* @throws ActivityProviderException
*/
public function getContextForAskAnythingByFilter(Request $request, ElasticActivityRepository $repository): JsonResponse
{
/** @var User $user */
$user = $request->user();
if ($featureCheck = $this->checkAskJiminnyOnAnythingFeature($user)) {
return $featureCheck;
}
$topCount = $request->input('top_count', self::DEFAULT_TOP_ACTIVITIES_COUNT);
try {
// Always fetch first N (top count) IDs
$onDemandActivitySearchCriteria = VO\Repository\OnDemandActivitySearch\Criteria::createFromRequest(
array_merge($request->all(), ['limit' => $topCount, 'page' => 1]),
$user->getTimezone()
);
$filterSet = $this->activitySearch->getOnDemandPageFilterSet($onDemandActivitySearchCriteria, $user);
$validationRules = $filterSet->getValidationRules()
->merge([
'exclude' => 'array',
'limit' => 'integer|min:1|max:' . $topCount,
])
->all();
$request->validate($validationRules);
$hasChangedFilters = $this->hasChangedContextFilter($request, $user);
$activityIds = $repository->onDemandSearchIdsOnly($user, $onDemandActivitySearchCriteria, $filterSet);
$this->historyService->storeContextIds($user, HistoryService::CONTEXT_IDS, $activityIds);
return new JsonResponse([
'count' => count($activityIds),
'changed_context_filters' => $hasChangedFilters,
], ResponseAlias::HTTP_OK);
} catch (Exception $e) {
$this->logger->error('Failed to fetch activity IDs for Ask Jiminny', [
'error' => $e->getMessage(),
'user_id' => $user->getId(),
]);
return new JsonResponse([
'ids' => [],
'error' => 'Failed to fetch activity IDs',
], ResponseAlias::HTTP_INTERNAL_SERVER_ERROR);
}
}
private function hasChangedContextFilter(Request $request, User $user): bool
{
$filterKey = $this->makeFilterKey($request);
$result = $this->historyService->compareAndSetFilterKeyWithHistory($user, $filterKey);
if (! $result['changed']) {
return false;
}
if ($result['matches_previous']) {
return false;
}
$history = $this->historyService->getHistory($user, HistoryService::ON_DEMAND_SERVICE);
// If no history or last event already matches, return false
if (empty($history) || $this->historyService->hasFilteredChangedEventAsLastMessage($history)) {
return false;
}
// Append event and notify
$this->historyService->appendToEventHistory(
user: $user,
identifier: HistoryService::ON_DEMAND_SERVICE,
type: HistoryService::EVENT_FILTERS_CHANGED_TYPE
);
return true;
}
private function makeFilterKey(Request $request): string
{
$filters = $request->except(self::FILTER_KEY_EXCLUDED_PARAMS);
try {
$normalizedFilters = FilterNormalizer::normalizeFilters($filters);
$json = json_encode(
$normalizedFilters,
JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE | JSON_THROW_ON_ERROR
);
return hash('xxh3', $json);
} catch (\JsonException $e) {
$this->logger->error('Failed to encode filters', [
'error' => $e->getMessage(),
'filters_keys' => array_keys($filters),
]);
throw new AskJiminnyException('Failed to create filter key', 0, $e);
}
}
/**
* Get Ask Anything conversation history
*/
public function getAskAnythingHistory(Request $request): JsonResponse
{
/** @var User $user */
$user = $request->user();
if ($featureCheck = $this->checkAskJiminnyOnAnythingFeature($user)) {
return $featureCheck;
}
try {
$history = $this->historyService->getHistory($user, HistoryService::ON_DEMAND_SERVICE);
return new JsonResponse($history, ResponseAlias::HTTP_OK);
} catch (Exception $e) {
$this->logger->error('Failed to fetch Ask Anything history', [
'error' => $e->getMessage(),
'user_id' => $user->getId(),
]);
return new JsonResponse([
'history' => [],
'error' => 'Failed to fetch history',
], ResponseAlias::HTTP_INTERNAL_SERVER_ERROR);
}
}
/**
* Delete Ask Anything conversation history
*/
public function deleteAskAnythingHistory(Request $request): JsonResponse
{
/** @var User $user */
$user = $request->user();
if ($featureCheck = $this->checkAskJiminnyOnAnythingFeature($user)) {
return $featureCheck;
}
try {
$this->historyService->deleteHistory($user, HistoryService::ON_DEMAND_SERVICE);
return new JsonResponse([
'message' => 'History deleted successfully',
], ResponseAlias::HTTP_OK);
} catch (Exception $e) {
$this->logger->error('Failed to delete Ask Anything history', [
'error' => $e->getMessage(),
'user_id' => $user->getId(),
]);
return new JsonResponse([
'error' => 'Failed to delete history',
], ResponseAlias::HTTP_INTERNAL_SERVER_ERROR);
}
}
/**
* Ask Anything - submit question and get AI response
*/
public function askAnything(OnDemandAskAnythingRequest $request): StreamedResponse|JsonResponse
{
/** @var User $user */
$user = $request->user();
$this->logger->info('AskAnything request received', [
'user_id' => $user->getId(),
'team_id' => $user->getTeamId(),
'request_hash' => md5($request->input('message') . $user->getId() . floor(time() / 60)),
'message_preview' => mb_substr($request->input('message'), 0, 50),
]);
if ($featureCheck = $this->checkAskJiminnyOnAnythingFeature($user)) {
return $featureCheck;
}
try {
$inputData = $request->validated();
$requestData = [
'userQuestion' => $inputData['message'],
'callIds' => $this->historyService->getContextIds($user, HistoryService::CONTEXT_IDS),
'history' => $this->historyService->getHistory($user, HistoryService::ON_DEMAND_SERVICE),
];
$teamAiContext = $this->teamAiContextRepository->getByTeamId($user->getTeamId());
if ($teamAiContext?->getPrompt() !== null) {
$requestData['teamAiContext'] = $teamAiContext->getPrompt();
}
$this->historyService->appendToUserHistory(
$user,
HistoryService::ON_DEMAND_SERVICE,
$inputData['message']
);
$this->historyService->appendToEventHistory(
user: $user,
identifier: HistoryService::ON_DEMAND_SERVICE,
type: HistoryService::EVENT_IN_PROGRESS_TYPE
);
$streamRequest = StreamRequest::onDemandLevel($requestData);
// Track active stream in Redis
$this->activeStreamsRepository->start(
$user->getId(),
$streamRequest->getId(),
ttlSeconds: $streamRequest->getConnectTimeout() + $streamRequest->getReadTimeout()
);
return $this->prophetService->getStreamedOrAbortedResponse(
streamRequest: $streamRequest,
onCompleted: function (
string $assistantResponse,
bool $clientAborted,
bool $hadError,
) use ($user, $streamRequest) {
// Remove in-progress event
$this->historyService->removeLastEventMessageByType(
$user,
HistoryService::ON_DEMAND_SERVICE,
HistoryService::EVENT_IN_PROGRESS_TYPE
);
// Save to history if backend completed successfully (even if client disconnected)
// Only skip saving if there was an actual error during streaming
if (! $hadError && ! empty(trim($assistantResponse))) {
$this->historyService->appendToSystemHistory(
$user,
HistoryService::ON_DEMAND_SERVICE,
$assistantResponse,
);
}
// Notify frontend if client disconnected (so it can update UI if still on page)
if ($clientAborted) {
$this->eventDispatcher->dispatch(
new AskAnythingAbortedChatCompleted(
user: $user,
identifier: HistoryService::ON_DEMAND_SERVICE,
response: $assistantResponse,
)
);
}
// Remove active stream in Redis
$this->activeStreamsRepository->stop($user->getId(), $streamRequest->getId());
}
);
} catch (Exception $e) {
$this->historyService->removeLastEventMessageByType(
$user,
HistoryService::ON_DEMAND_SERVICE,
HistoryService::EVENT_IN_PROGRESS_TYPE
);
$this->logger->error('Failed to process Ask Anything request', [
'error' => $e->getMessage(),
'user_id' => $user->getId(),
'question' => $request->input('message'),
]);
return new JsonResponse([
'error' => 'Failed to process your question',
], ResponseAlias::HTTP_INTERNAL_SERVER_ERROR);
}
}
public function stopStream(Request $request): JsonResponse
{
$user = $request->user();
$this->activeStreamsRepository->stopByUser($user->getId());
$this->historyService->removeLastEventMessageByType(
$user,
HistoryService::ON_DEMAND_SERVICE,
HistoryService::EVENT_IN_PROGRESS_TYPE
);
return response()->json(['message' => 'Stream marked as stopped by user']);
}
}
Sync Changes
Hide This Notification
Code changed:
Hide
15
4
Previous Highlighted Error
Next Highlighted Error
<?php
declare(strict_types=1);
namespace Jiminny\Repositories;
use Carbon\CarbonImmutable;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Support\Carbon;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Pagination\LengthAwarePaginator;
use Illuminate\Support\Facades\DB;
use Jiminny\Models\AutomatedReport;
use Jiminny\Models\AutomatedReportResult;
use Jiminny\Models\Team;
use Jiminny\Models\User;
use Jiminny\Services\Kiosk\AutomatedReports\AutomatedReportsService;
use Jiminny\Services\Kiosk\AutomatedReports\ReportSort;
use Jiminny\Services\Kiosk\AutomatedReports\ReportSortDirection;
class AutomatedReportsRepository
{
/**
* Create a new automated report
*
* @param array $data
*
* @return AutomatedReport
*/
public function create(array $data): AutomatedReport
{
return AutomatedReport::create($data);
}
/**
* Find an automated report by UUID
*
* @param string $uuid
*
* @return AutomatedReport|null
*/
public function findByUuid(string $uuid): ?AutomatedReport
{
return AutomatedReport::where('uuid', AutomatedReport::toOptimized($uuid))->first();
}
public function findByIdOrUuid(string $idOrUuid): ?AutomatedReport
{
if (is_numeric($idOrUuid)) {
return AutomatedReport::find((int) $idOrUuid);
}
return AutomatedReport::where('uuid', AutomatedReport::toOptimized($idOrUuid))->first();
}
/**
* Retrieve all standard (non-Ask Jiminny) automated reports.
*
* @param string $sortColumn The column to sort by. Allowed values: 'created_by', 'created_at'. Defaults to 'created_at'.
* @param string $sortDirection The sort direction. Allowed values: 'asc', 'desc'. Defaults to 'desc'.
*
* @return Collection<AutomatedReport>
*/
public function getAllStandardReports(
string $sortColumn = 'created_at',
string $sortDirection = 'desc'
): Collection {
return $this->buildSortedQuery($sortColumn, $sortDirection)
->whereNot('type', AutomatedReportsService::TYPE_ASK_JIMINNY)
->get();
}
/**
* Retrieve all Ask Jiminny reports created by the given user.
*
* @param User $user The user whose reports to retrieve.
* @param string $sortColumn The column to sort by. Allowed values: 'created_by', 'created_at'. Defaults to 'created_at'.
* @param string $sortDirection The sort direction. Allowed values: 'asc', 'desc'. Defaults to 'desc'.
*
* @return Collection<AutomatedReport>
*/
public function getAskJiminnyReportsByUser(
User $user,
string $sortColumn = 'created_at',
string $sortDirection = 'desc'
): Collection {
return $this->buildSortedQuery($sortColumn, $sortDirection)
->where('type', AutomatedReportsService::TYPE_ASK_JIMINNY)
->where('created_by', $user->getId())
->get();
}
private function buildSortedQuery(string $sortColumn, string $sortDirection): \Illuminate\Database\Eloquent\Builder
{
$allowedColumns = ['created_by', 'created_at'];
if (! in_array($sortColumn, $allowedColumns)) {
$sortColumn = 'created_at';
}
$sortDirection = strtolower($sortDirection) === 'asc' ? 'asc' : 'desc';
$query = AutomatedReport::query()->with(['creator', 'team']);
if ($sortColumn === 'created_by') {
$query->leftJoin('users', 'users.id', '=', 'automated_reports.created_by')
->orderByRaw("users.name COLLATE utf8mb4_unicode_ci {$sortDirection}")
->select('automated_reports.*');
} else {
$query->orderBy($sortColumn, $sortDirection);
}
return $query;
}
/**
* Get all active and enabled reports with active teams for the specified frequency.
*
* @param string $frequency
*
* @return Collection<AutomatedReport>
*/
public function getActiveReportsByFrequency(string $frequency): Collection
{
return AutomatedReport::where('automated_reports.status', true)
->where('automated_reports.frequency', $frequency)
->join('teams', 'automated_reports.team_id', '=', 'teams.id')
->where('teams.status', Team::STATUS_ACTIVE)
->where(function ($query) {
$query->whereNull('automated_reports.expires_at')
->orWhere('automated_reports.expires_at', '>=', now()->toDateString());
})
->select('automated_reports.*')
->get();
}
/**
* Update an automated report
*
* @param AutomatedReport $report
* @param array $data
*
* @return AutomatedReport
*/
public function update(AutomatedReport $report, array $data): AutomatedReport
{
$report->update($data);
return $report;
}
/**
* Create a new automated report result.
*
* @param array $data The data to create the automated report result with.
*
* @return AutomatedReportResult The newly created automated report result.
*/
public function createResult(array $data): AutomatedReportResult
{
return AutomatedReportResult::create($data);
}
/**
* Find an automated report result by UUID.
*
* @param string $uuid The UUID to find the automated report result with.
*
* @return AutomatedReportResult|null The automated report result if found, otherwise null.
*/
public function findResultByUuid(string $uuid): ?AutomatedReportResult
{
return AutomatedReportResult::where('uuid', AutomatedReportResult::toOptimized($uuid))->first();
}
public function findResultByUuidForUser(string $uuid, User $user): ?AutomatedReportResult
{
return AutomatedReportResult::query()
->where('uuid', AutomatedReportResult::toOptimized($uuid))
->whereHas('report', static function ($query) use ($user): void {
$query->where('team_id', $user->getTeamId())
->where('created_by', $user->getId());
})
->first();
}
public function findChildResult(AutomatedReportResult $result, string $type): ?AutomatedReportResult
{
return AutomatedReportResult::query()
->where('parent_id', $result->getId())
->where('media_type', $type)
->first();
}
public function getGeneratedNotSentResults(): Collection
{
return AutomatedReportResult::query()
->whereNotNull('generated_at')
->whereNull('sent_at')
->where('status', AutomatedReportResult::STATUS_GENERATED)
->whereHas('report')
->with('report')
->get();
}
public function getPaginatedUserReports(
User $user,
ReportSort $sort,
ReportSortDirection $sortDirection,
int $resultsPerPage,
int $page,
?Carbon $fromDate,
?Carbon $toDate,
array $teamIds,
array $reportTypes,
?string $name,
): LengthAwarePaginator {
$query = AutomatedReportResult::query()
->whereNotNull('automated_report_results.generated_at')
->join('automated_reports', 'automated_report_results.report_id', '=', 'automated_reports.id')
->where('automated_reports.team_id', $user->getTeamId())
->whereJsonContains('automated_reports.recipients->users', $user->getId())
->orderByRaw("$sort->value COLLATE utf8mb4_unicode_ci {$sortDirection->value}")
->select('automated_report_results.*')
->with('report.team');
if ($fromDate !== null && $toDate !== null) {
$query->whereBetween('generated_at', [$fromDate, $toDate]);
}
if (! empty($teamIds)) {
$query->where(function ($q) use ($teamIds) {
foreach ($teamIds as $id) {
$q->orWhereJsonContains('automated_reports.groups', $id);
}
});
}
if (! empty($reportTypes)) {
$query->whereIn('automated_reports.type', $reportTypes);
}
if (! empty($name)) {
$query->whereLike('name', "%$name%");
}
return $query->paginate($resultsPerPage, ['*'], 'page', $page);
}
public function countUserReports(User $user): int
{
return AutomatedReportResult::query()
->whereNotNull('generated_at')
->whereNotNull('sent_at')
->whereHas('report', function ($q) use ($user) {
$q->where('team_id', $user->getTeamId())
->whereJsonContains('recipients->users', $user->getId());
})
->count();
}
/**
* Get report IDs for a specific team
*
* @param Team $team
*
* @return \Illuminate\Support\Collection
*/
public function getReportIdsByTeam(Team $team): \Illuminate\Support\Collection
{
return AutomatedReport::where('team_id', $team->getId())->pluck('id');
}
/**
* Get all reports for a specific team
*
* @param Team $team
*
* @return Collection
*/
public function getReportsByTeam(Team $team): Collection
{
return AutomatedReport::where('team_id', $team->getId())->get();
}
/**
* Get all report results for a specific report
*
* @param AutomatedReport $report
*
* @return Collection
*/
public function getResultsByReport(AutomatedReport $report): Collection
{
return $this->getResultsByReportQuery($report)->get();
}
public function getResultsByReportQuery(AutomatedReport $report): Builder
{
return AutomatedReportResult::where('report_id', $report->getId());
}
public function getReportResultsQueryForRetention(Team $team, CarbonImmutable $retentionDate): Builder
{
$reportIds = $this->getReportIdsByTeam($team);
return AutomatedReportResult::query()->whereIn('report_id', $reportIds)
->whereRaw('IFNULL(generated_at, created_at) <= ?', [$retentionDate]);
}
/**
* @param int|null $teamId Optional team ID to filter results
*
* @return \Illuminate\Support\Collection<int, int> Collection of team IDs
*/
public function getTeamIdsWithReportsResults(?int $teamId = null): \Illuminate\Support\Collection
{
$query = DB::table('automated_reports')
->join('teams', 'automated_reports.team_id', '=', 'teams.id')
->select('teams.id')
->distinct();
if ($teamId !== null) {
$query->where('teams.id', $teamId);
}
return $query->pluck('teams.id');
}
}
Project
Project
New File or Directory…
Expand Selected
Collapse All
Options
Hide...
|
PhpStorm
|
faVsco.js – OnDemandV2Controller.php
|
NULL
|
11073
|
|
11072
|
Project: faVsco.js, menu
#11894 on JY-18909-automa Project: faVsco.js, menu
#11894 on JY-18909-automated-reports-ask-jiminny, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceT…Defaults
Run 'AskJiminnyReportActivityServiceTest.tes…uenceNumberToDisableFirstRequestDefaults'
Debug 'AskJiminnyReportActivityServiceTest.tes…uenceNumberToDisableFirstRequestDefaults'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Sync Changes
Hide This Notification
Code changed:
Hide
PhpStormFileEditViewNavigateCodeLaravelRefactorToolsWindowHelpFV faVsco.s v#11894 on JY-18909-automated-reports-ask-liminny k vProject v© ReportController.phpJiminnybeouecommana.ong© AutomatedReportsCommand.php© AutomatedReportsSendCommand.php© AddLayoutEntities.php© Team.php© AutomatedReportsRepository.php X© AutomatedReportsService.phpC CreateHeldActivityEvent.php, 0lablf Support Daily • in 2h 49 mA100% C•Tue 14 Apr 12:11:23AskJiminnyReportActivityServiceT…Defaults© JiminnyDebugCommanc© JiminnySetEncryptedTo© JiminnyTokenInfoComn© MakeSlackLiveCoachins© ManageScimForTeam.p(c Malkoanchrocnvronnlc Mureu canzercnanner© PhpApm.php(C) PropagateCoachingFee© PurgeConferences.php© PurgeSoftDeletedOppor© PurgeSyncBatchesComiC RecalculateDealRisksCa© RemoveDeleteMarkersC© RemoveExpiredNudgesi© RemoveUnusedParticip:© ResetElasticsearch.phpc resto eAcctvrvcimrroy© RestoreActivityTypeCor© SeedActivities.php© SyncActivity.php©Tracklmported.php© UpdateActivitiesAverag© WhichWorkerlsWorkingr> D Scheduling© Kernel.php> D Contracts> M Domain> MDTO> M Emails› _ Enums> D Events> D Exceptions> DJ FFMpeg>D Formats› D Guards› Helpersv UHttp> MAccessTokenProviderv D ControllersV DAPI> DAiCallScoringAiReports> D Deallnsights> D Opportunity> C Page> • Scorecards> D SettingsTeamInsightsnemes> MUserAutomatedRepov DV2© ActivityV2ControlAskAnythingCont© AskJiminnyReporl© DealsV2Controlle:© OnDemandV2Con© PlaylistController.© PlaylistShareContTests passed: 1 (2 minutes ago)= custom.log< console EUi= laravel.logA SF [jiminny@localhost]A HS_local [jiminny@localhost]A console [PROD]console SlAGiNG© AskJiminnyReportActivityService.php© ActivitySearch.pnpCascadeFixing ReportControllerAutomated Report MarFixing Ask Jiminny Rep+D..(e TrackProvidernstallled-vent.ono© CreateActivityLoggedEvent.php© UserPilotActivityListener.php(©) ActivityLogged.php(C) AutomatedReportsCallbackService.php© RequestGenerateAskJiminnyReportJob.phpRequestGenerateReportJob.php© AutomatedReportResult.php(C) AutomatedReport.phpclass Automacedкeрortskepo o:B15 X4 AOnDemandV2Controller.php x© FilterDefinitionCollection.php© Criteria.php© AskJiminnyReportActivityServiceTest.php© RequestGenerateAskJiminnyReportJobTest.phpclass OnDemandV2Controller extends Controller47public function_construct(opnetservice spropnetservicemAiContextRepository $teamAiContextRepository,FiveStreamsRepository $activeStreamsRepository,intDispatcher $eventDispatcher,igerInterface $logger,Now let's run the test to verify41 M2 ^wtests/Unxt/Servsces/Kiosk/Automate/meports/AskJ1minnyreportActivätyserviceTest-php --no-coveragecould not open input Tile: /var/www/ncml/artisanCommand dockeldoster nxe ceockes /kJosk/AuP /ape/a/poras/A5kJ1minyReportActivityServiceTest.php --no-coverageCould not open input file: /app/artisanealn nos wne hox suiN oN Any rimo reccure endotee61931141151161171181191211124123/**> ikJiminnyOnAnythingFeature(User $user): ?JsonResponsef...}Command dockeroocker exec oocker vand ioash -c"cd /var/www&& php artisan testLests unlu services Klosk Aucomaceakeporcs AskJiminnykeportAccivityservicelest.ono =-no-coverade D&l'Could not open input file: artisan* Retrieve all standard (non-Ask Jiminny) Mis for Ask Jiminny feature based on filters* @param string $sortColumnThe column to* dodron scrino osorcuurection ine sort oulreCommand docken• docker exec docker_lamp_1 bash -c "find / -name artisan -maxdepth 6 2>/dev/null | head -5"/home/jiminny/artisan* @return Collection<AutomatedReport>ceptioniderException12 usages78 Qg › :xtForAskAnythingByFilter(Request $request, ElasticActivityRepository $repository): JsonRespons."cd /homee/jiminny && php artisan testpublic function getAllStandardReports(tests/nxe erckee/Kio5/AutonateReports/5KJimamyReportActivaty ServiceTest, php --no-coverage 2561"string $sortColumn = 'created_at',PASSstring $sortDirection = 'desc'127): Collection {...J› igedContextFilter(Request $request, User $user): boolf...}getTests\Unit\Services\Kiosk\AutomatedReports\AskJiminnyReportActivityServiceTest157filtersemoty when no results/*** Retrieve all Ask Liminny reports created› _terKey(Request $request): string{...}E tatt tnt hperiod date filtersids bassess snazer fsequence number to disable first _ 0.025* Oodrdll usernusenIne user YnosAll 8 tests pass. Here's a summary:* @param string $sortColumnThe column to* Oparam string $sortDirection The sort direversation historyRoot Cause & FixRoot cause: buildRequestParamsFromSearch never set sequence number in the request params, so Criteria::createFromRequest defaulted it to 0* @return Collection<AutomatedReport>Since isFirstRequest() returns true when sequenceNumber === 0, several implicit defaults were silently applied:184 Qg › lythingHistory(Request $request): JsonResponse{...}*/Activitvourat ionRande → min duration = 1 ilters ouf o-second activitiesi-20814 usagesActivityRecorded → only_recorded = 1 (restricts to recorded activities only)209public function getAskJiminnyReportsByUser(OrganiserGroupIn → applies user's default group as a filtel-210conversation historyUser $user,211The frontend URL you noticed uses sequence_number=4, which disables these defaults - explaining why the frontend returned activities but the servicestring $sortColumn = 'created_at',returned O.string ssorcbirection = "desc"Fix: AskJiminnyReportActivityService.php:51—added 'sequence_number' → 1 to the Criteria::createFromRequest merge, ensuring isFirstReque): Collection {...J212 (Q › ikAnythingHistory(Request $request): JsonResponsef...}st() returns false and no implicit defaults are injected.237Test added: testGetActLeylasPassesNonzerosequencenumberloD1sablerirsckequestberauuus asserts that the captured uriteria ob ect nas 1srirs— 238tRequest () === false.2 usagesprivate function buildSortedQuery(string $sor239question and aet AT responseÖul ../*** Get all active and enabled reports with a<349241 (g> láng(OnDemandASKAnythingRequest Srequest): StreamedResponselJsonResponse(... 3* @param string $frequencyVew allli350 (g > tam(Request $request): JsonResponse{...}Itlle wiun changesvapp/Services/Kiosk/AutomatedReports/D AskJiminnyReportActivityService.php +1 -1-364* dreturn cocLectron<Aucomacedкeрort»Reject allAccept all365Explain it to me again. Why is there issue with that? Where is it expected and wy do l need to fork with that. How is it used in23 usagespublic function getActiveReportsByFrequency(s+ <> Code Claude Sonnet 4.6Winasun leamsuir-o( 4 spaces...
|
PhpStorm
|
faVsco.js – OnDemandV2Controller.php
|
NULL
|
11072
|
|
11071
|
Project: faVsco.js, menu
#11894 on JY-18909-automa Project: faVsco.js, menu
#11894 on JY-18909-automated-reports-ask-jiminny, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceT…Defaults
Run 'AskJiminnyReportActivityServiceTest.tes…uenceNumberToDisableFirstRequestDefaults'
Debug 'AskJiminnyReportActivityServiceTest.tes…uenceNumberToDisableFirstRequestDefaults'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Sync Changes
Hide This Notification
Code changed:
Hide
+SlackEDHomeDMSActivityFilesLater..•More+FileEditViewGoHistoryWindowHelpJiminny ...# Starredplatform-inner-teamChannels# ai-chapter# alerts# backend# confusion-clinic# curiosity_lab# engineering# frontend# general# infra-changes# jiminny-bg# platform-tickets# product_launches# random# releases# sofia-office# support# thank-yous# the_people_of jimi…..Direct messagesAneliya Angelova, ...Steliyan GeorgievAdelina Petrova, Ili.... Adelina PetrovaO. Calea Dimitravo→Search Jiminny IncAneliya Angelova, Nikolay Yankov, Steliyan GeorgievMessagesAdd canvas+Nikolay Yankov 10:45 AMпиши кат оя рьннешLukas Kovalik 10:52 AMзабавих се че ми се разбазикаха settings за средипуснах и мина и fail-наима result но e failedзначиREASON_NOT_ENOUGH_ACTIVITIESвиж дали има нещо в OD със този филтьрNikolay Yankov 11:01 AMДобреNikolay Yankov 11:39 AMя рьнни пак LukasLukas Kovalik 11:43 AMготовосьщотоCompetitive pitches беше втория нали такаNikolay Yankov 12:04 PMДа, там има 14 активитита, защо не сработи този пьт?Lukas Kovalik 12:05 PMпак изглежда sequenceгледам гоMessage Aneliya Angelova, Nikolay Yankov, Steliyan Georgiev+Aalal]Support Daily - in 2h 49 m100% <47Tue 14 Apr 12:11:238Today ~...
|
PhpStorm
|
faVsco.js – OnDemandV2Controller.php
|
NULL
|
11071
|
|
11070
|
Project: faVsco.js, menu
#11894 on JY-18909-automa Project: faVsco.js, menu
#11894 on JY-18909-automated-reports-ask-jiminny, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceT…Defaults
Run 'AskJiminnyReportActivityServiceTest.tes…uenceNumberToDisableFirstRequestDefaults'
Debug 'AskJiminnyReportActivityServiceTest.tes…uenceNumberToDisableFirstRequestDefaults'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Sync Changes
Hide This Notification
Code changed:
Hide
1
2
Previous Highlighted Error
Next Highlighted Error
<?php
declare(strict_types=1);
namespace Jiminny\Http\Controllers\API\V2;
use Exception;
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Routing\Controller;
use Illuminate\Validation\ValidationException;
use Jiminny\Component\ActivitySearch\Service\ActivitySearch;
use Jiminny\Component\AskAnything\HistoryService;
use Jiminny\Component\AskJiminnyAi\Exceptions\AskJiminnyException;
use Jiminny\Component\AskJiminnyAi\OnDemandLevel\Events\AskAnythingAbortedChatCompleted;
use Jiminny\Component\Prophet\ProphetService;
use Jiminny\Component\ProphetAi\StreamRequest;
use Jiminny\Events\EventDispatcher;
use Jiminny\Exceptions\ActivityProviderException;
use Jiminny\Http\Requests\API\V2\OnDemandAskAnythingRequest;
use Jiminny\Models\Feature\FeatureEnum;
use Jiminny\Models\User;
use Jiminny\Repositories\ActiveStreamsRepository;
use Jiminny\Repositories\ElasticActivityRepository;
use Jiminny\Repositories\TeamAiContextRepository;
use Jiminny\Utils\FilterNormalizer;
use Jiminny\VO;
use Psr\Log\LoggerInterface;
use Symfony\Component\HttpFoundation\Response as ResponseAlias;
use Symfony\Component\HttpFoundation\StreamedResponse;
class OnDemandV2Controller extends Controller
{
use AuthorizesRequests;
private const int DEFAULT_TOP_ACTIVITIES_COUNT = 100;
private const array FILTER_KEY_EXCLUDED_PARAMS = [
'sequence_number',
'page',
'per_page',
'limit',
'offset',
];
public function __construct(
private readonly ActivitySearch $activitySearch,
private readonly HistoryService $historyService,
private readonly ProphetService $prophetService,
private readonly TeamAiContextRepository $teamAiContextRepository,
private readonly ActiveStreamsRepository $activeStreamsRepository,
private readonly EventDispatcher $eventDispatcher,
private readonly LoggerInterface $logger,
) {
}
/**
* Check if the user's team has the ASK_JIMINNY_ON_ANYTHING feature enabled
*/
private function checkAskJiminnyOnAnythingFeature(User $user): ?JsonResponse
{
if (! $user->team->hasFeature(FeatureEnum::ASK_JIMINNY_ON_ANYTHING)) {
return new JsonResponse([
'message' => 'Feature ASK_JIMINNY_ON_ANYTHING is not enabled for this team',
], ResponseAlias::HTTP_FORBIDDEN);
}
return null;
}
/**
* Get top N activity IDs for Ask Jiminny feature based on filters
*
* @throws ValidationException
* @throws ActivityProviderException
*/
public function getContextForAskAnythingByFilter(Request $request, ElasticActivityRepository $repository): JsonResponse
{
/** @var User $user */
$user = $request->user();
if ($featureCheck = $this->checkAskJiminnyOnAnythingFeature($user)) {
return $featureCheck;
}
$topCount = $request->input('top_count', self::DEFAULT_TOP_ACTIVITIES_COUNT);
try {
// Always fetch first N (top count) IDs
$onDemandActivitySearchCriteria = VO\Repository\OnDemandActivitySearch\Criteria::createFromRequest(
array_merge($request->all(), ['limit' => $topCount, 'page' => 1]),
$user->getTimezone()
);
$filterSet = $this->activitySearch->getOnDemandPageFilterSet($onDemandActivitySearchCriteria, $user);
$validationRules = $filterSet->getValidationRules()
->merge([
'exclude' => 'array',
'limit' => 'integer|min:1|max:' . $topCount,
])
->all();
$request->validate($validationRules);
$hasChangedFilters = $this->hasChangedContextFilter($request, $user);
$activityIds = $repository->onDemandSearchIdsOnly($user, $onDemandActivitySearchCriteria, $filterSet);
$this->historyService->storeContextIds($user, HistoryService::CONTEXT_IDS, $activityIds);
return new JsonResponse([
'count' => count($activityIds),
'changed_context_filters' => $hasChangedFilters,
], ResponseAlias::HTTP_OK);
} catch (Exception $e) {
$this->logger->error('Failed to fetch activity IDs for Ask Jiminny', [
'error' => $e->getMessage(),
'user_id' => $user->getId(),
]);
return new JsonResponse([
'ids' => [],
'error' => 'Failed to fetch activity IDs',
], ResponseAlias::HTTP_INTERNAL_SERVER_ERROR);
}
}
private function hasChangedContextFilter(Request $request, User $user): bool
{
$filterKey = $this->makeFilterKey($request);
$result = $this->historyService->compareAndSetFilterKeyWithHistory($user, $filterKey);
if (! $result['changed']) {
return false;
}
if ($result['matches_previous']) {
return false;
}
$history = $this->historyService->getHistory($user, HistoryService::ON_DEMAND_SERVICE);
// If no history or last event already matches, return false
if (empty($history) || $this->historyService->hasFilteredChangedEventAsLastMessage($history)) {
return false;
}
// Append event and notify
$this->historyService->appendToEventHistory(
user: $user,
identifier: HistoryService::ON_DEMAND_SERVICE,
type: HistoryService::EVENT_FILTERS_CHANGED_TYPE
);
return true;
}
private function makeFilterKey(Request $request): string
{
$filters = $request->except(self::FILTER_KEY_EXCLUDED_PARAMS);
try {
$normalizedFilters = FilterNormalizer::normalizeFilters($filters);
$json = json_encode(
$normalizedFilters,
JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE | JSON_THROW_ON_ERROR
);
return hash('xxh3', $json);
} catch (\JsonException $e) {
$this->logger->error('Failed to encode filters', [
'error' => $e->getMessage(),
'filters_keys' => array_keys($filters),
]);
throw new AskJiminnyException('Failed to create filter key', 0, $e);
}
}
/**
* Get Ask Anything conversation history
*/
public function getAskAnythingHistory(Request $request): JsonResponse
{
/** @var User $user */
$user = $request->user();
if ($featureCheck = $this->checkAskJiminnyOnAnythingFeature($user)) {
return $featureCheck;
}
try {
$history = $this->historyService->getHistory($user, HistoryService::ON_DEMAND_SERVICE);
return new JsonResponse($history, ResponseAlias::HTTP_OK);
} catch (Exception $e) {
$this->logger->error('Failed to fetch Ask Anything history', [
'error' => $e->getMessage(),
'user_id' => $user->getId(),
]);
return new JsonResponse([
'history' => [],
'error' => 'Failed to fetch history',
], ResponseAlias::HTTP_INTERNAL_SERVER_ERROR);
}
}
/**
* Delete Ask Anything conversation history
*/
public function deleteAskAnythingHistory(Request $request): JsonResponse
{
/** @var User $user */
$user = $request->user();
if ($featureCheck = $this->checkAskJiminnyOnAnythingFeature($user)) {
return $featureCheck;
}
try {
$this->historyService->deleteHistory($user, HistoryService::ON_DEMAND_SERVICE);
return new JsonResponse([
'message' => 'History deleted successfully',
], ResponseAlias::HTTP_OK);
} catch (Exception $e) {
$this->logger->error('Failed to delete Ask Anything history', [
'error' => $e->getMessage(),
'user_id' => $user->getId(),
]);
return new JsonResponse([
'error' => 'Failed to delete history',
], ResponseAlias::HTTP_INTERNAL_SERVER_ERROR);
}
}
/**
* Ask Anything - submit question and get AI response
*/
public function askAnything(OnDemandAskAnythingRequest $request): StreamedResponse|JsonResponse
{
/** @var User $user */
$user = $request->user();
$this->logger->info('AskAnything request received', [
'user_id' => $user->getId(),
'team_id' => $user->getTeamId(),
'request_hash' => md5($request->input('message') . $user->getId() . floor(time() / 60)),
'message_preview' => mb_substr($request->input('message'), 0, 50),
]);
if ($featureCheck = $this->checkAskJiminnyOnAnythingFeature($user)) {
return $featureCheck;
}
try {
$inputData = $request->validated();
$requestData = [
'userQuestion' => $inputData['message'],
'callIds' => $this->historyService->getContextIds($user, HistoryService::CONTEXT_IDS),
'history' => $this->historyService->getHistory($user, HistoryService::ON_DEMAND_SERVICE),
];
$teamAiContext = $this->teamAiContextRepository->getByTeamId($user->getTeamId());
if ($teamAiContext?->getPrompt() !== null) {
$requestData['teamAiContext'] = $teamAiContext->getPrompt();
}
$this->historyService->appendToUserHistory(
$user,
HistoryService::ON_DEMAND_SERVICE,
$inputData['message']
);
$this->historyService->appendToEventHistory(
user: $user,
identifier: HistoryService::ON_DEMAND_SERVICE,
type: HistoryService::EVENT_IN_PROGRESS_TYPE
);
$streamRequest = StreamRequest::onDemandLevel($requestData);
// Track active stream in Redis
$this->activeStreamsRepository->start(
$user->getId(),
$streamRequest->getId(),
ttlSeconds: $streamRequest->getConnectTimeout() + $streamRequest->getReadTimeout()
);
return $this->prophetService->getStreamedOrAbortedResponse(
streamRequest: $streamRequest,
onCompleted: function (
string $assistantResponse,
bool $clientAborted,
bool $hadError,
) use ($user, $streamRequest) {
// Remove in-progress event
$this->historyService->removeLastEventMessageByType(
$user,
HistoryService::ON_DEMAND_SERVICE,
HistoryService::EVENT_IN_PROGRESS_TYPE
);
// Save to history if backend completed successfully (even if client disconnected)
// Only skip saving if there was an actual error during streaming
if (! $hadError && ! empty(trim($assistantResponse))) {
$this->historyService->appendToSystemHistory(
$user,
HistoryService::ON_DEMAND_SERVICE,
$assistantResponse,
);
}
// Notify frontend if client disconnected (so it can update UI if still on page)
if ($clientAborted) {
$this->eventDispatcher->dispatch(
new AskAnythingAbortedChatCompleted(
user: $user,
identifier: HistoryService::ON_DEMAND_SERVICE,
response: $assistantResponse,
)
);
}
// Remove active stream in Redis
$this->activeStreamsRepository->stop($user->getId(), $streamRequest->getId());
}
);
} catch (Exception $e) {
$this->historyService->removeLastEventMessageByType(
$user,
HistoryService::ON_DEMAND_SERVICE,
HistoryService::EVENT_IN_PROGRESS_TYPE
);
$this->logger->error('Failed to process Ask Anything request', [
'error' => $e->getMessage(),
'user_id' => $user->getId(),
'question' => $request->input('message'),
]);
return new JsonResponse([
'error' => 'Failed to process your question',
], ResponseAlias::HTTP_INTERNAL_SERVER_ERROR);
}
}
public function stopStream(Request $request): JsonResponse
{
$user = $request->user();
$this->activeStreamsRepository->stopByUser($user->getId());
$this->historyService->removeLastEventMessageByType(
$user,
HistoryService::ON_DEMAND_SERVICE,
HistoryService::EVENT_IN_PROGRESS_TYPE
);
return response()->json(['message' => 'Stream marked as stopped by user']);
}
}
Sync Changes
Hide This Notification
Code changed:
Hide
15
4
Previous Highlighted Error
Next Highlighted Error
<?php
declare(strict_types=1);
namespace Jiminny\Repositories;
use Carbon\CarbonImmutable;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Support\Carbon;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Pagination\LengthAwarePaginator;
use Illuminate\Support\Facades\DB;
use Jiminny\Models\AutomatedReport;
use Jiminny\Models\AutomatedReportResult;
use Jiminny\Models\Team;
use Jiminny\Models\User;
use Jiminny\Services\Kiosk\AutomatedReports\AutomatedReportsService;
use Jiminny\Services\Kiosk\AutomatedReports\ReportSort;
use Jiminny\Services\Kiosk\AutomatedReports\ReportSortDirection;
class AutomatedReportsRepository
{
/**
* Create a new automated report
*
* @param array $data
*
* @return AutomatedReport
*/
public function create(array $data): AutomatedReport
{
return AutomatedReport::create($data);
}
/**
* Find an automated report by UUID
*
* @param string $uuid
*
* @return AutomatedReport|null
*/
public function findByUuid(string $uuid): ?AutomatedReport
{
return AutomatedReport::where('uuid', AutomatedReport::toOptimized($uuid))->first();
}
public function findByIdOrUuid(string $idOrUuid): ?AutomatedReport
{
if (is_numeric($idOrUuid)) {
return AutomatedReport::find((int) $idOrUuid);
}
return AutomatedReport::where('uuid', AutomatedReport::toOptimized($idOrUuid))->first();
}
/**
* Retrieve all standard (non-Ask Jiminny) automated reports.
*
* @param string $sortColumn The column to sort by. Allowed values: 'created_by', 'created_at'. Defaults to 'created_at'.
* @param string $sortDirection The sort direction. Allowed values: 'asc', 'desc'. Defaults to 'desc'.
*
* @return Collection<AutomatedReport>
*/
public function getAllStandardReports(
string $sortColumn = 'created_at',
string $sortDirection = 'desc'
): Collection {
return $this->buildSortedQuery($sortColumn, $sortDirection)
->whereNot('type', AutomatedReportsService::TYPE_ASK_JIMINNY)
->get();
}
/**
* Retrieve all Ask Jiminny reports created by the given user.
*
* @param User $user The user whose reports to retrieve.
* @param string $sortColumn The column to sort by. Allowed values: 'created_by', 'created_at'. Defaults to 'created_at'.
* @param string $sortDirection The sort direction. Allowed values: 'asc', 'desc'. Defaults to 'desc'.
*
* @return Collection<AutomatedReport>
*/
public function getAskJiminnyReportsByUser(
User $user,
string $sortColumn = 'created_at',
string $sortDirection = 'desc'
): Collection {
return $this->buildSortedQuery($sortColumn, $sortDirection)
->where('type', AutomatedReportsService::TYPE_ASK_JIMINNY)
->where('created_by', $user->getId())
->get();
}
private function buildSortedQuery(string $sortColumn, string $sortDirection): \Illuminate\Database\Eloquent\Builder
{
$allowedColumns = ['created_by', 'created_at'];
if (! in_array($sortColumn, $allowedColumns)) {
$sortColumn = 'created_at';
}
$sortDirection = strtolower($sortDirection) === 'asc' ? 'asc' : 'desc';
$query = AutomatedReport::query()->with(['creator', 'team']);
if ($sortColumn === 'created_by') {
$query->leftJoin('users', 'users.id', '=', 'automated_reports.created_by')
->orderByRaw("users.name COLLATE utf8mb4_unicode_ci {$sortDirection}")
->select('automated_reports.*');
} else {
$query->orderBy($sortColumn, $sortDirection);
}
return $query;
}
/**
* Get all active and enabled reports with active teams for the specified frequency.
*
* @param string $frequency
*
* @return Collection<AutomatedReport>
*/
public function getActiveReportsByFrequency(string $frequency): Collection
{
return AutomatedReport::where('automated_reports.status', true)
->where('automated_reports.frequency', $frequency)
->join('teams', 'automated_reports.team_id', '=', 'teams.id')
->where('teams.status', Team::STATUS_ACTIVE)
->where(function ($query) {
$query->whereNull('automated_reports.expires_at')
->orWhere('automated_reports.expires_at', '>=', now()->toDateString());
})
->select('automated_reports.*')
->get();
}
/**
* Update an automated report
*
* @param AutomatedReport $report
* @param array $data
*
* @return AutomatedReport
*/
public function update(AutomatedReport $report, array $data): AutomatedReport
{
$report->update($data);
return $report;
}
/**
* Create a new automated report result.
*
* @param array $data The data to create the automated report result with.
*
* @return AutomatedReportResult The newly created automated report result.
*/
public function createResult(array $data): AutomatedReportResult
{
return AutomatedReportResult::create($data);
}
/**
* Find an automated report result by UUID.
*
* @param string $uuid The UUID to find the automated report result with.
*
* @return AutomatedReportResult|null The automated report result if found, otherwise null.
*/
public function findResultByUuid(string $uuid): ?AutomatedReportResult
{
return AutomatedReportResult::where('uuid', AutomatedReportResult::toOptimized($uuid))->first();
}
public function findResultByUuidForUser(string $uuid, User $user): ?AutomatedReportResult
{
return AutomatedReportResult::query()
->where('uuid', AutomatedReportResult::toOptimized($uuid))
->whereHas('report', static function ($query) use ($user): void {
$query->where('team_id', $user->getTeamId())
->where('created_by', $user->getId());
})
->first();
}
public function findChildResult(AutomatedReportResult $result, string $type): ?AutomatedReportResult
{
return AutomatedReportResult::query()
->where('parent_id', $result->getId())
->where('media_type', $type)
->first();
}
public function getGeneratedNotSentResults(): Collection
{
return AutomatedReportResult::query()
->whereNotNull('generated_at')
->whereNull('sent_at')
->where('status', AutomatedReportResult::STATUS_GENERATED)
->whereHas('report')
->with('report')
->get();
}
public function getPaginatedUserReports(
User $user,
ReportSort $sort,
ReportSortDirection $sortDirection,
int $resultsPerPage,
int $page,
?Carbon $fromDate,
?Carbon $toDate,
array $teamIds,
array $reportTypes,
?string $name,
): LengthAwarePaginator {
$query = AutomatedReportResult::query()
->whereNotNull('automated_report_results.generated_at')
->join('automated_reports', 'automated_report_results.report_id', '=', 'automated_reports.id')
->where('automated_reports.team_id', $user->getTeamId())
->whereJsonContains('automated_reports.recipients->users', $user->getId())
->orderByRaw("$sort->value COLLATE utf8mb4_unicode_ci {$sortDirection->value}")
->select('automated_report_results.*')
->with('report.team');
if ($fromDate !== null && $toDate !== null) {
$query->whereBetween('generated_at', [$fromDate, $toDate]);
}
if (! empty($teamIds)) {
$query->where(function ($q) use ($teamIds) {
foreach ($teamIds as $id) {
$q->orWhereJsonContains('automated_reports.groups', $id);
}
});
}
if (! empty($reportTypes)) {
$query->whereIn('automated_reports.type', $reportTypes);
}
if (! empty($name)) {
$query->whereLike('name', "%$name%");
}
return $query->paginate($resultsPerPage, ['*'], 'page', $page);
}
public function countUserReports(User $user): int
{
return AutomatedReportResult::query()
->whereNotNull('generated_at')
->whereNotNull('sent_at')
->whereHas('report', function ($q) use ($user) {
$q->where('team_id', $user->getTeamId())
->whereJsonContains('recipients->users', $user->getId());
})
->count();
}
/**
* Get report IDs for a specific team
*
* @param Team $team
*
* @return \Illuminate\Support\Collection
*/
public function getReportIdsByTeam(Team $team): \Illuminate\Support\Collection
{
return AutomatedReport::where('team_id', $team->getId())->pluck('id');
}
/**
* Get all reports for a specific team
*
* @param Team $team
*
* @return Collection
*/
public function getReportsByTeam(Team $team): Collection
{
return AutomatedReport::where('team_id', $team->getId())->get();
}
/**
* Get all report results for a specific report
*
* @param AutomatedReport $report
*
* @return Collection
*/
public function getResultsByReport(AutomatedReport $report): Collection
{
return $this->getResultsByReportQuery($report)->get();
}
public function getResultsByReportQuery(AutomatedReport $report): Builder
{
return AutomatedReportResult::where('report_id', $report->getId());
}
public function getReportResultsQueryForRetention(Team $team, CarbonImmutable $retentionDate): Builder
{
$reportIds = $this->getReportIdsByTeam($team);
return AutomatedReportResult::query()->whereIn('report_id', $reportIds)
->whereRaw('IFNULL(generated_at, created_at) <= ?', [$retentionDate]);
}
/**
* @param int|null $teamId Optional team ID to filter results
*
* @return \Illuminate\Support\Collection<int, int> Collection of team IDs
*/
public function getTeamIdsWithReportsResults(?int $teamId = null): \Illuminate\Support\Collection
{
$query = DB::table('automated_reports')
->join('teams', 'automated_reports.team_id', '=', 'teams.id')
->select('teams.id')
->distinct();
if ($teamId !== null) {
$query->where('teams.id', $teamId);
}
return $query->pluck('teams.id');
}
}
Project
Project
New File or Directory…
Expand Selected
Collapse All
Options
Hide
app ~/jiminny/app
.circleci
.cursor
.github
.sonarlint
.vscode
.windsurf
app, sources root
Actions
Component
Acl, folder
ActionItems, folder
Activity, folder
ActivityAnalytics, folder
ActivitySearch, folder
EventSubscriber, folder
FilterDefinition, folder
Service
ActivityApiSearch.php, class
ActivitySearch.php, class
UserOptionsByGroup.php, class
AbstractStageFilterDefinition.php, abstract class
ActivitySearchServiceProvider.php, final class
DealInsightsPeriodFilterFactory.php
DealInsightsPeriodFilterFactoryInterface.php, interface
FilterDefinition.php, abstract class
FilterDefinitionCollection.php, class
FilterDefinitionQuery.php, class
FilterDefinitionQueryCollection.php, class
FilteredValueContainerInterface.php, interface
IntMinMaxRange.php, class
AiActivityType
AiAutomation
AiCallScoring
AskAnything
AskJiminnyAi
AWS
BillingManagement
Cache
CoachingFeedback
Country
CustomerApi
Database
Datadog
DateTime
DealInsights
DealRisks
ElasticSearch
Eloquent
Encoding
Encryption
ES
Faker
FeatureFlags
FFMpeg
FileSystem
Gecko
Gong
GuzzleHttp
KeyPoints
Kiosk
LanguageDetection
LiveFeed
Locks
Math
MediaPipeline
MeetingBot
MobileSettings
Model
Notification
Nudge
ParagraphBreaker
ParticipantSpeech
PartitionedCookie
PlaybackPage
Playlist
Prophet
ProphetAi, folder
ProsperWorks, folder
Queue, folder
Router, folder
Saml2, folder
SCIM, folder
Seeder, folder
Sentry, folder
Serializer, folder
Settings, folder
Sidekick, folder
Slack, folder
TeamInsights, folder
TimeMemoryMapper, folder
Transcription, folder
TranscriptionSummary, folder
Twilio, folder
Uploader, folder
UrlGenerator, folder
Utility, folder
Uuid, folder
Waveform, folder
Webhooks, folder
Workflow, folder
Configuration
Console
Commands
Activities
Analytics
Calendars
Crm
Hubspot
IntegrationApp
AddLayoutEntities.php, class
AutologDelayedCommand.php, class
BullhornCommandAbstract.php, abstract class
BullhornPingCommand.php, class
BullhornSearchCommand.php, class
BullhornSessionCommand.php, class
CheckActivityLoggableCommand.php, final class
CleanDuplicateFieldDataCommand.php, class
FullSyncOpportunityCommand.php, class
LogActivitiesCommand.php, final class
ManageSyncStrategyCommand.php, class
MatchCrmObjectsCommand.php, class
MatchOpportunityActivitiesCommand.php, class
MigrateProvider.php, class
ProcessHubspotObjectsSyncBatches.php, class
PurgeDeletedOpportunitiesCommand.php, class
ResetGovernorLimits.php, class
SendNotLogged.php, class
SetupActivityTypeForFollowUp.php, final class
SetupCloseCrm.php, class
SetupCopperCrm.php, class
SetupCrmCommand.php, abstract class
SetupLayouts.php, class
SyncAccount.php, class
SyncContact.php, class
SyncFieldMetadata.php, class
SyncHubspotActiveDeals.php, class
SyncLead.php, class
SyncObjects.php, class
SyncOpportunitiesMissingFieldDataCommand.php, class
SyncOpportunity.php, class
SyncProfileMetadata.php, class
SyncTeamMetadata.php, class
UpdateOpportunitySpecifications.php, class
DealInsights
Dev
Dialers
DTOs
Elasticsearch
EngagementStats
GeckoExport
Livestream
Mailboxes
Migrate
PlaybackThemes
Playbooks
Playlists
Postmark
ProphetAi
Reports
AutomatedReportsCommand.php, class
AutomatedReportsRetentionPolicyCommand.php, class
AutomatedReportsSendCommand.php, class
CreateMockAskJiminnyReportResultCommand.php, class
DeleteReportCommand.php, class
GenerateMarketingReport.php, class
Team.php, class
Usage.php, class...
|
PhpStorm
|
faVsco.js – OnDemandV2Controller.php
|
NULL
|
11070
|
|
11069
|
PhpStormFileEditViewNavigateCodeLaravelRefactorToo PhpStormFileEditViewNavigateCodeLaravelRefactorToolsWindowHelp, 0lablj Support Daily • in 2h 49 mA100% |45]Tue 14 Apr 12:11:11FV faVsco.s v#11894 on JY-18909-automated-reports-ask-iminny K vAskJiminnyReportActivityServiceT…DefaultsProject v© ReportController.phpyJiminnyDeouecommana.ong= custom.log= laravel.logA SF [jiminny@localhost]A HS_local [jiminny@localhost]A console [PROD]Cascadev ServiceAulomaleakeporscommand.ono< console LUlconsole SlAGiNG© AskJiminnyReportActivityService.php© ActivitySearch.php xFixing ReportControllerAutomated Report MarFixing Ask Jiminny Rep© ActivityApiSearch.ph© ActivitySearch.php© AutomatedReportsSendCommand.phpAddLayoutEntities.php© FilterDefinitionCollection.php© Criteria.php© AskJiminnyReportActivityServiceTest.phpNow let's run the test to verifv© UserOptionsByGrour© Team.php© AutomatedReportsRepository.php XRequestGenerateAskJiminnyReportJobTest.php© AbstractStageFilterDefil© AutomatedReportsService.phpC CreateHeldActivityEvent.phpActivitySearchServicePrsronoCommand dockenwC DeallnsightsPeriodFilter(e TrackProvidernstallled-vent.onodeclare(strict_types=1);o desker nxe dovkcrs/ko3k Automwa/wprts/art1nan yReportActivityserviceTest-php --no-coverage0 DealinsidnisPeriodrilten© CreateActivityLoggedEvent.php© UserPilotActivityListener.phploul nor oen ndlr Tler var wi nunbarusang FilterDetinition.php(©) ActivityLogged.phpnamespace Jiminny\Component\ActivitySearch\Service;) Aulomaleakeporscallbackservice.onoc rterverntoncolectoCommand dockel© FilterDefinitionQuery.ph© RequestGenerateAskJiminnyReportJob.php› use ...© FilterDefinitionQueryColA Naalinn auna daalian lama 1 abaRequestGenerateReportJob.php© AutomatedReportResult.phpassesllesSymbolsActionsextProiect HllesvTiminnyReportActivityServiceTest.php --no-coverage• FilteredValueContainerliclass ActivitvSearch© IntMinMaxRange.php(C) AutomatedReport.phpQ- OnDemal[ AiActivityTypeclass Automacedкeрortskepo o:815 X4 л7 usages[ AiAutomationprivate Container $container;DOnDemandActivitySearch app/VO/Repository/OnDemandActivitySearchD AiCallScoring© OnDemandController.php•aoo nuo controlers Ariraee unvemanacontroler.ono&& php artisan testJiminnyReportActivityServiceTest.php --no-coverage 2>&1"D AskAnythingpublic function __construct(Container $container)f.© OnDemandActivitiesTransformer.php .../app/Http/Transformers/OnDemandActivitiesTransformer.phpD AskJiminnyAi* Retrieve all standard (non-Ask Jiminny) M• OnDemandLevel app/Component/AskJiminnyAi/OnDemandLevelDAWSpublic function get0nDemandPageFilters(): FilterDefir© OnDemandAskAnythingRequest.php .../app/Http/Requests/API/V2/OnDemandAskAnythingRequest.pM BillinaManagement59* @param string $sortColumnIne column tc-oe© OnDemandV2Controller.php.../app/Http/Controllers/API/V2/OnDemandV2Controller.phpM Cache* Oparam string $sortDirection The sort dire 107public function getOnDemandPageFilterSet(Criteria $crOnDemandActivitySearch build/coverage/VO/Repository/OnDemandActivitySearche artisan -maxdeoth 6 2>/dev/null | head -5"• CoachingFeedback_108OnDemandV2ControllerTest.php .../tests/Unit/Http/Controllers/Api/V2/OnDemandV2ControllerTest.p> D Country*orerurn coccecclonsauromceoreooro109return $this<> OnDemandController.php.html build/coverage/Http/Controllers/APl/PageD CustomerApi• Database->getOnDemandPageFilters()‹/ OnvemanoAcrvrescnstommerono.numi oullc/covercerruoanstommers12 usages111-›withCriteria($criteria)<> OndemandController.php.html build/coverage/Http/ControllersC Datadogpublic function getAllStandardReports(112->withConsumer($consumer)ninny && php artisan testJiminnyReportActivityServiceTest-php --no-coverage 2>&1"C DateTimestring $sortColumn = 'created_at',Deallnsights113->withRestrictions($consumer->getTeam()):string $sortDirection = 'desc'114_ DealRisksEasticsearch): Collection {...J115poy wen n resporatet ipamtereseempty when no results116 F>_tloquent> DEncoding/**1171 date filters* Retrieve all Ask Liminny reports created f118number to disable first r... 0.03s> D Encryption9 usagesDES* OodrdllusernusenThe user whos 119public function getArrayFilterKeys(User $consumer): aD Faker* @param string $sortColumnThe column tc 130• FeatureFlags* Oparam string $sortDirection The sort dire1 usageD FFMpeg1151private function getTeamInsightsPageFilters(bool $isEsence number in the request params, so criceria:: creater romkequest deraultea itlo 0• FileSystem- === 0, several implicit defaults were silently applied:* Oreturn Collection<AutomatedReport>1Y1D Geckoto-second acrivitiesD Gong14 usagesprivate function getDealInsightsPageFilters(corded activities only)GuzzleHttppublic function getAskJiminnyReportsByUser(199bool $useCreatedDate = false,KeyPointsUser $user,-200bool $includeDealType = false,• Kioskch disables these defaults - explaining why the frontend returned activities but the servicestring $sortColumn = 'created_at',bool $includePipeline = false,M LanquadeDetectionstring ssorcbirection = "desc"202): FilterDefinitionCollection {.+LiveFeed): Collection {...J232sequence_number' → 1 to the Criteria:: createFromRequest merge, ensuring isFirstRequevukepositoryonbemaneAcuivilysearchOpen In Right SplitD Locks253public function getTeamInsightsPageFilterSet(lestadded: testoetAculvlcyLaspassesnonzerosequencenumberlob1sablerursckequestberau Lus asserts that the captured urlterla oblect nas 1shirs• MathZ usages1254cricerta pcracerta,tRequest() === false.• MediaPipelineprivate function buildSortedQuery(string $sor235user +consumer,Oul .• MeetingBot114250bool sisExport = false• MobileSettings115/**237): FilterDefinitionCollection {..| ModelNotitication116* Get all active and enabled reports with ac 244117Nudge245public function getDealInsightsPageFilterSet(118* @param string $frequency246Criteria $criteria,Vew allliParagraphBreakerItlle wiun changesv119247User $consumerapp/Services/Kiosk/AutomatedReports/D AskJiminnyReportActivityService.php +1 -1M ParticipantSpeech120* dreturn cocLectron<Aucomacedкeрort»248): Falterbefinitioncollection i...rReject allAccept allPartitionedCookie121D PlaybackPage258Explain it to me again. Why is there issue with that? Where is it expected and wy do l need to fork with that. How is it used ir23 usages1 usagePlaylist1124public function getActiveReportsByFrequency(:259pubLic tuncclon getleamA1AutomationFilterSet(123+ <> Code Claude Sonnet 4.6Tests passed: 1 (2 minutes ago)winasun leams118.duir-o( 4 spaces...
|
NULL
|
NULL
|
NULL
|
11069
|
|
11068
|
PhpStormFileEditViewNavigateCodeLaravelRefactorFV PhpStormFileEditViewNavigateCodeLaravelRefactorFV faVsco.s v#11894 on JY-18909-automated-reports-ask-liminny k vProject v© ReportController.phpToolsWindowHelpyJiminnyDeouecommana.ongv Service© ActivityApiSearch.ph© ActivitySearch.php© UserOptionsByGrour© AbstractStageFilterDefilActivitySearchServicePrC DeallnsightsPeriodFilter0 Dealinsichisperiodrilterg FilterDetinition.phpc rterverntoncolecto© FilterDefinitionQuery.ph© FilterDefinitionQueryCol• FilteredValueContainerli© IntMinMaxRange.php[ AiActivityType[ AiAutomationD AiCallScoringD AskAnythingD AskJiminnyAiDAWSM BillinaManagementM Cache• CoachingFeedback> D CountryD CustomerApi• DatabaseC DatadogC DateTimeDeallnsights_ DealRisksEasticsearch>_tloquent> DEncoding> D EncryptionDESD Faker• FeatureFlagsD FFMpeg• FileSystemD GeckoD GongGuzzleHttpKeyPoints• KioskM LanquageDetectionLiveFeedD Locks• Math• MediaPipeline• MeetingBot• MobileSettings| ModelNotiticationNudgeParagraphBreakerM ParticipantSpeechPartitionedCookieD PlaybackPagePlaylistAulomaleakeporscommand.ono© AutomatedReportsSendCommand.phpAddLayoutEntities.php© Team.php© AutomatedReportsRepository.php X© AutomatedReportsService.phpC CreateHeldActivityEvent.php= custom.log= laravel.logA SF [jiminny@localhost]A HS_local [jiminny@localhost]A console [PROD]< console LUlconsole SlAGiNG© AskJiminnyReportActivityService.php© ActivitySearch.php x© FilterDefinitionCollection.php© Criteria.php© AskJiminnyReportActivityServiceTest.phpRequestGenerateAskJiminnyReportJobTest.phpsrono(e) TrackProvidernstallled-vent.onodeclare(strict_types=1);© CreateActivityLoggedEvent.php(©) ActivityLogged.php© UserPilotActivityListener.php(C) AutomatedReportsCallbackService.phpnamespace Jiminny\Component\ActivitySearch\Service;© RequestGenerateAskJiminnyReportJob.phpRequestGenerateReportJob.php(C) AutomatedReport.php› use ...© AutomatedReportResult.phpclass ActivitvSearchclass Automacedкeрortskepo o:815 X4 л591141151161171181191201211124123Tests passed: 1 (2 minutes ago)/*** Retrieve all standard (non-Ask Jiminny) M* @param string $sortColumnIne column tc-oe* Oparam string $sortDirection The sort dire 107* @return Collection<AutomatedReport>-10810912 usagespublic function getAllStandardReports(string $sortColumn = 'created_at',string $sortDirection = 'desc'): Collection {...J/**114113114115116117* Retrieve all Ask Liminny reports created &118* OodrdllusernusenThe user whos 119* @param string $sortColumnThe column tc 130* Oparam string $sortDirection The sort dire1151* Oreturn Collection<AutomatedReport>1Y1*/14 usagespublic function getAskJiminnyReportsByUser(199User $user,-200string $sortColumn = 'created_at',string ssorcbirection = "desc"): Collection {...}202232253Z usages/**1254private function buildSortedQuery(string $sor235250237* Get all active and enabled reports with ac244245* @param string $frequency246247* dreturh coLcectzon<aucomacedкeрort>24825823 usagespublic function getActiveReportsByFrequency(:2597 usagesprivate Container $container;public function __construct(Container $container){...}public function getOnDemandPageFilters(): FilterDefinitionCollectionf...}public function getOnDemandPageFilterSet(Criteria $criteria, User $consumer): FilterDefinitreturn $this->getOnDemandPageFilters()->nunenainchuerlay->withConsumer ($consumer)->withRestrictions($consumer->getTeam()):9 usagespublic function getArrayFilterkeys (User Sconsumer) : Errayt....1 usageprivate function getTeamInsightsPageFilters(bool $isExport = false): FilterDefinitionCollecprivate function getDealInsightsPageFilters(bool $useCreatedDate = false,bool $includeDealType = false,bool $includePipeline = false,): FilterDefinitionCollection {.+public function getTeamInsightsPageFilterSet(cricerta pcracerta,user +consumer,bool sisExport = false): FilterDefinitionCollection {...public function getDealInsightsPageFilterSet(Criteria $criteria,User $consumer): FalterDefinitionCollection1 usagepubLic tunccion getleamAlAucomacionriltersetl, 0lablf Support Daily • in 2h 49 mAAskJiminnyReportActivityServiceT…Defaults100% C•Tue 14 Apr 12:11:09CascadeFixing ReportControllerAutomated Report MarFixing Ask Jiminny Rep+D ...Now let's run the test to verifvtests/Unxt/Servsces/Kiosk/Automate/meports/AskJ1minnyreportActivätyserviceTest-php --no-coverageloul nor oen nolt tler var w nunwaru sanCommand dockeldoster nxe ceockes /kJosk/AuP /ape/a/poras/A5kJ1minyReportActivityServiceTest. php --no-coverageCould not open input file: /app/artisanCommand dockeroocker exec oocker vand ioash -cSid php artisan testLests unlu services Klosk Aucomaceakeporcs AskJiminnykeportAccivityservicelest.ono =-no-coverade D&l'Could not open input file: artisan• docker exec docker_lamp_1 bash -c "find / -name artisan -maxdepth 6 2>/dev/null | head -5"/home/jiminny/artisan"cd /homeiminny && php artisan testdests/unxe/servaces/K1osk/AusomatedReports/AskJ1maynyReportActivaty5erviceTest-php --no-coverage 2>61"PASSgetTests\Unit\Services\Kiosk\AutomatedReports\AskJiminnyReportActivityServiceTestemoty when no resultsperiod date filters1ds handles scrayr tittersids bassess snazer fsequence number to disable first _ 0.025All 8 tests pass. Here's a summary:Root Cause & FixKoOL cause: bu1 Ldkequestraramst romsearch never set sequence number In the request params, so criterla::creater romkequest delaulted lt to 0Since isFirstRequest() returns true when sequenceNumber === 0, several implicit defaults were silently applied:Activitvourat ionRande → min duration = 1 Tilters ouf o-second activitiesiActivityRecorded → only_recorded = 1 (restricts to recorded activities only)OrganiserGroupIn → applies user's default group as a filtelThe frontend URL you noticed uses sequence_number=4, which disables these defaults - explaining why the frontend returned activities but the servicereturnee oFix: AskJiminnyReportActivityService.php:51 —added 'sequence_number' → 1 to the Criteria: :createFromRequest merge, ensuring isFirstRequest() returns false and no implicit defaults are injected.lest added: testbetaccLeylasPassesNonzerosequencenumberloD1sablerirsckequestberauuus asserts that the captured uriteria ob ect nas 1srirstRequest() === false.Öul ..Vew allliItlle wiun changesvapp/Services/Kiosk/AutomatedReports/D AskJiminnyReportActivityService.php +1 -1Reject allAccept allExplain it to me again. Why is there issue with that? Where is it expected and wy do l need to fork with that. How is it used in+ <> Code Claude Sonnet 4.6W Windsurf Teams11T:Z0uir-o( 4 spaces...
|
NULL
|
NULL
|
NULL
|
11068
|
|
11067
|
+SlackEDHomeDMSActivityFilesLater..•More+FileEditV +SlackEDHomeDMSActivityFilesLater..•More+FileEditViewGoHistoryWindowHelpJiminny ...# Starredplatform-inner-teamChannels# ai-chapter# alerts# backend# confusion-clinic# curiosity_lab# engineering# frontend# general# infra-changes# jiminny-bg# platform-tickets# product launches# random# releases# sofia-office# support# thank-yous# the_people_of jimi…..Direct messagesAneliya Angelova, ...Steliyan GeorgievAdelina Petrova, Ili.... Adelina PetrovaO. Calea Dimitravo→Search Jiminny IncAneliya Angelova, Nikolay Yankov, Steliyan GeorgievMessagesAdd canvas+Nikolay Yankov 10:45 AMпиши кат оя рьннешLukas Kovalik 10:52 AMзабавих се че ми се разбазикаха settings за средипуснах и мина и fail-наима result но e failedзначиREASON_NOT_ENOUGH_ACTIVITIESвиж дали има нещо в OD със този филтьрNikolay Yankov 11:01 AMДобреNikolay Yankov 11:39 AMя рьнни пак LukasLukas Kovalik 11:43 AMготовосьщотоCompetitive pitches беше втория нали такаNikolay Yankov 12:04 PMДа, там има 14 активитита, защо не сработи този пьт?Lukas Kovalik 12:05 PMпак изглежда sequenceгледам гоMessage Aneliya Angelova, Nikolay Yankov, Steliyan Georgiev+Aalal]Support Daily - in 2h 49 m100% <47Tue 14 Apr 12:11:0986 0Today ~...
|
NULL
|
NULL
|
NULL
|
11067
|
|
11066
|
PhpStormFileEditViewNavigateCodeLaravelRefactorFV PhpStormFileEditViewNavigateCodeLaravelRefactorFV faVsco.s v#11894 on JY-18909-automated-reports-ask-liminny k vProject v© ReportController.phpToolsWindowHelpyJiminnyDeouecommana.ongv Service© ActivityApiSearch.ph© ActivitySearch.php© UserOptionsByGrour© AbstractStageFilterDefilActivitySearchServicePrC DeallnsightsPeriodFilter0 DealinsidnisPeriodrilteng FilterDetinition.phpc rterverntoncolecto© FilterDefinitionQuery.ph© FilterDefinitionQueryCol• FilteredValueContainerli© IntMinMaxRange.php[ AiActivityType[ AiAutomationD AiCallScoringD AskAnythingD AskJiminnyAiDAWSM BillinaManagementM Cache• CoachingFeedback> D CountryD CustomerApi• DatabaseC DatadogC DateTimeDeallnsights_ DealRisksEasticsearch>_tloquent> DEncoding> D EncryptionDESD Faker• FeatureFlagsD FFMpeg• FileSystemD GeckoD GongGuzzleHttpKeyPoints• KioskM LanquadeDetectionLiveFeedD Locks• Math• MediaPipeline• MeetingBot• MobileSettings| ModelNotiticationNudgeParagraphBreakerM ParticipantSpeechPartitionedCookieD PlaybackPagePlaylistTnesstatAulomaleakeporscommand.ono© AutomatedReportsSendCommand.phpAddLayoutEntities.php© Team.php© AutomatedReportsRepository.php X© AutomatedReportsService.phpC CreateHeldActivityEvent.php= custom.log= laravel.logA SF [jiminny@localhost]A HS_local [jiminny@localhost]A console [PROD]< console EUiconsole SlAGiNG© AskJiminnyReportActivityService.php© ActivitySearch.php x© FilterDefinitionCollection.php© Criteria.php© AskJiminnyReportActivityServiceTest.phpRequestGenerateAskJiminnyReportJobTest.phpsrono(e) TrackProvidernstallled-vent.onodeclare(strict_types=1);© CreateActivityLoggedEvent.php(©) ActivityLogged.php© UserPilotActivityListener.php(C) AutomatedReportsCallbackService.phpnamespace Jiminny\Component\ActivitySearch\Service;© RequestGenerateAskJiminnyReportJob.phpRequestGenerateReportJob.php© AutomatedReportResult.php(C) AutomatedReport.phpclass Automacedкeрortskepo o:815 X4 л› use ...class ActivitvSearch591141151161171181191201211124123lests passed: (a minute ago/*** Retrieve all standard (non-Ask Jiminny) M* @param string $sortColumnIne column tc-oe* Oparam string $sortDirection The sort dire 107-108*orerurn coccecclonsauromceoreooro10912 usagespublic function getAllStandardReports(string $sortColumn = 'created_at',string $sortDirection = 'desc'): Collection {...J/**114113114115116117* Retrieve all Ask Liminny reports created 2118* OodrdllusernusenThe user whos 119* @param string $sortColumnThe column tc 130* Oparam string $sortDirection The sort dire1151* Oreturn Collection<AutomatedReport>1Y114 usagespublic function getAskJiminnyReportsByUser(199User $user,-200string $sortColumn = 'created_at',string ssorcbirection = "desc"202): Collection {...}232253Z usages/**1254private function buildSortedQuery(string $sor235250237* Get all active and enabled reports with ac244245* @param string $frequency246247* dreturh coLcectzon<aucomacedкeрort>24825823 usagespublic function getActiveReportsByFrequency(:2597 usagesprivate Container $container;public function __construct(Container $container)f...}public function getOnDemandPageFilters(): FilterDefinitionCollectionf...}public function getOnDemandPageFilterSet(Criteria $criteria, User Sconsumer): FilterDefinitreturn $this->getOnDemandPageFilters()->nunenainchuerlay->withConsumer ($consumer)->withRestrictions($consumer->getTeam()):9 usagespublic function getArrayFilterKeys(User $consumer): arrayf..31 usageprivate function getTeamInsightsPageFilters(bool $isExport = false): FilterDefinitionCollecprivate function getDealInsightsPageFilters(bool $useCreatedDate = false,bool $includeDealType = false,bool $includePipeline = false,): FilterDefinitionCollection {.+public function getTeamInsightsPageFilterSet(cricerta pcracerta,user +consumer,bool sisExport = false): FilterDefinitionCollection {...public function getDealInsightsPageFilterSet(Criteria $criteria,User $consumer): FalterDefinitionCollection{..1 usagepubLic tunccion getleamAlAucomacionriltersetlSupport Daily • in 2 h 50 mAAskJiminnyReportActivityServiceT…Defaults100% C•Tue 14 Apr 12:10:50+D ..CascadeFixing ReportControllerAutomated Report MarFixing Ask Jiminny RepNow let's run the test to verifvtests/Unxt/Servsces/Kiosk/Automate/meports/AskJ1minnyreportActivätyserviceTest-php --no-coverageloul nor oen ndlr Tler var ww nunbarusanCommand dockerdoster nxe ceockes /kJosk/AuPo/ape/a/ports/ASkJ1minyReportActivityServiceTest. php --no-coverageCould not open input file: /app/artisanCommand docker•cocker exec oocker vand ioash —dSid php artisan testtests/Unit/Services/Kiosk/AutomatedReports/AskJiminnyReportActivityServiceTest.php —-no-coverage 2>&1"Could not open input file: artisan• docker exec docker_lamp_1 bash -c "find / -name artisan -maxdepth 6 2>/dev/null | head -5"/home/jiminny/artisan"cd /homeiminny && php artisan test•dests/unxe/servkces/K1osk/AusomatedReports/AskJ1maynyReportActiVatyServiceTest.php --no-coverage 2>&1"PASSgetTests\Unit\Services\Kiosk\AutomatedReports\AskJiminnyReportActivityServiceTesta fittersemoty when no resultsperiod date filters1de handtes scalyr flttersids bassess snazer fsequence number to disable first _ 0.025All 8 tests pass. Here's a summary:Root Cause & FixKoOL cause: bu1 Ldkequestraramst romsearch never set sequence number In the request params, so criterla::creater romkequest delaulted lt to 0Since isFirstRequest() returns true when sequenceNumber === 0, several implicit defaults were silently applied:ActivityDurationRange → min_duration = 1 (filters out 0-second activities)ActivityRecorded → only_recorded = 1 (restricts to recorded activities only)OrganiserGroupin → apolies user's derault croup as a tilterThe frontend URL you noticed uses sequence_number=4, which disables these defaults - explaining why the frontend returned activities but the servicereturnee o.Fix: AskJiminnyReportActivityService.php:51 —added 'sequence_number' → 1 to the Criteria: :createFromRequest merge, ensuring isFirstRequest() returns false and no implicit defaults are injected.lest added: testbetacc1cylasPassesNonzerosequencenumberloDisablerarsckequestberaulus assers that the captured uriteria ob ect nas 1srirstRequest() === false.Öul ..Vew allliItlle wiun changesvapp/Services/Kiosk/AutomatedReports/D AskJiminnyReportActivityService.php +1 -1Reject allAccept allExplain it to me again. Why is there issue with that+ <> Code Claude Sonnet 4.6W Windsurf Teams11T:Z0uir-o( 4 spaces...
|
NULL
|
NULL
|
NULL
|
11066
|
|
11065
|
+SlackEDHomeDMSActivityFilesLater..•More+FileEditV +SlackEDHomeDMSActivityFilesLater..•More+FileEditViewGoHistoryWindowHelpJiminny ...# Starredplatform-inner-teamChannels# ai-chapter# alerts# backend# confusion-clinic# curiosity_lab# engineering# frontend# general# infra-changes# jiminny-bg# platform-tickets# product_launches# random# releases# sofia-office# support# thank-yous# the_people_of jimi…..Direct messagesAneliya Angelova, ...Steliyan GeorgievAdelina Petrova, Ili.... Adelina PetrovaO. Calea Dimitravo→Search Jiminny IncAneliya Angelova, Nikolay Yankov, Steliyan GeorgievMessagesAdd canvas+Nikolay Yankov 10:45 AMпиши кат оя рьннешLukas Kovalik 10:52 AMзабавих се че ми се разбазикаха settings за средипуснах и мина и fail-наима result но e failedзначиREASON_NOT_ENOUGH_ACTIVITIESвиж дали има нещо в OD със този филтьрNikolay Yankov 11:01 AMДобреNikolay Yankov 11:39 AMя рьнни пак LukasLukas Kovalik 11:43 AMготовосьщотоCompetitive pitches беше втория нали такаNikolay Yankov 12:04 PMДа, там има 14 активитита, защо не сработи този пьт?Lukas Kovalik 12:05 PMпак изглежда sequenceгледам гоMessage Aneliya Angelova, Nikolay Yankov, Steliyan Georgiev+Aa> 0ladl= Support Daily • in 2h 50 m100% <47Tue 14 Apr 12:10:5086 0Today ~...
|
NULL
|
NULL
|
NULL
|
11065
|
|
11064
|
Project: faVsco.js, menu
#11894 on JY-18909-automa Project: faVsco.js, menu
#11894 on JY-18909-automated-reports-ask-jiminny, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceT…Defaults
Run 'AskJiminnyReportActivityServiceTest.tes…uenceNumberToDisableFirstRequestDefaults'
Debug 'AskJiminnyReportActivityServiceTest.tes…uenceNumberToDisableFirstRequestDefaults'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Sync Changes
Hide This Notification
Code changed:
Hide
PhpStormFileEditViewNavigateCodeLaravelRefactorFV faVsco.s v#11894 on JY-18909-automated-reports-ask-liminny k vProject v© ReportController.phpToolsWindowHelpyJiminnyDeouecommana.ongv Service© ActivityApiSearch.ph© ActivitySearch.php© UserOptionsByGrour© AbstractStageFilterDefilActivitySearchServicePrC DeallnsightsPeriodFilter0 DealinsidnisPeriodrilteng FilterDetinition.phpc rterverntoncolecto© FilterDefinitionQuery.ph© FilterDefinitionQueryCol• FilteredValueContainerli© IntMinMaxRange.php[ AiActivityType[ AiAutomationD AiCallScoringD AskAnythingD AskJiminnyAiDAWSM BillinaManagementM Cache• CoachingFeedback> D CountryD CustomerApi• DatabaseC DatadogC DateTimeDeallnsights_ DealRisksEasticsearch>_tloquent> DEncoding> D EncryptionDESD Faker• FeatureFlagsD FFMpeg• FileSystemD GeckoD GongGuzzleHttpKeyPoints• KioskM LanquadeDetectionLiveFeedD Locks• Math• MediaPipeline• MeetingBot• MobileSettings| ModelNotiticationNudgeParagraphBreakerM ParticipantSpeechPartitionedCookieD PlaybackPagePlaylistTnesstatAulomaleakeporscommand.ono© AutomatedReportsSendCommand.phpAddLayoutEntities.php© Team.php© AutomatedReportsRepository.php X© AutomatedReportsService.phpC CreateHeldActivityEvent.php= custom.log= laravel.logA SF [jiminny@localhost]A HS_local [jiminny@localhost]A console [PROD]< console EUiconsole SlAGiNG© AskJiminnyReportActivityService.php© ActivitySearch.php x© FilterDefinitionCollection.php© Criteria.php© AskJiminnyReportActivityServiceTest.phpRequestGenerateAskJiminnyReportJobTest.phpsrono(e) TrackProvidernstallled-vent.onodeclare(strict_types=1);© CreateActivityLoggedEvent.php(©) ActivityLogged.php© UserPilotActivityListener.php(C) AutomatedReportsCallbackService.phpnamespace Jiminny\Component\ActivitySearch\Service;© RequestGenerateAskJiminnyReportJob.phpRequestGenerateReportJob.php© AutomatedReportResult.php(C) AutomatedReport.phpclass Automacedкeрortskepo o:815 X4 л› use ...class ActivitvSearch591141151161171181191201211124123lests passed: (a minute ago/*** Retrieve all standard (non-Ask Jiminny) M* @param string $sortColumnIne column tc-oe* Oparam string $sortDirection The sort dire 107-108*orerurn coccecclonsauromceoreooro10912 usagespublic function getAllStandardReports(string $sortColumn = 'created_at',string $sortDirection = 'desc'): Collection {...J/**114113114115116117* Retrieve all Ask Liminny reports created 2118* OodrdllusernusenThe user whos 119* @param string $sortColumnThe column tc 130* Oparam string $sortDirection The sort dire1151* Oreturn Collection<AutomatedReport>1Y114 usagespublic function getAskJiminnyReportsByUser(199User $user,-200string $sortColumn = 'created_at',string ssorcbirection = "desc"202): Collection {...}232253Z usages/**1254private function buildSortedQuery(string $sor235250237* Get all active and enabled reports with ac244245* @param string $frequency246247* dreturh coLcectzon<aucomacedкeрort>24825823 usagespublic function getActiveReportsByFrequency(:2597 usagesprivate Container $container;public function __construct(Container $container)f...}public function getOnDemandPageFilters(): FilterDefinitionCollectionf...}public function getOnDemandPageFilterSet(Criteria $criteria, User Sconsumer): FilterDefinitreturn $this->getOnDemandPageFilters()->nunenainchuerlay->withConsumer ($consumer)->withRestrictions($consumer->getTeam()):9 usagespublic function getArrayFilterKeys(User $consumer): arrayf..31 usageprivate function getTeamInsightsPageFilters(bool $isExport = false): FilterDefinitionCollecprivate function getDealInsightsPageFilters(bool $useCreatedDate = false,bool $includeDealType = false,bool $includePipeline = false,): FilterDefinitionCollection {.+public function getTeamInsightsPageFilterSet(cricerta pcracerta,user +consumer,bool sisExport = false): FilterDefinitionCollection {...public function getDealInsightsPageFilterSet(Criteria $criteria,User $consumer): FalterDefinitionCollection{..1 usagepubLic tunccion getleamAlAucomacionriltersetlSupport Daily • in 2 h 50 mAAskJiminnyReportActivityServiceT…Defaults100% C•Tue 14 Apr 12:10:45CascadeFixing ReportControllerAutomated Report MarFixing Ask Jiminny Rep+D ..Now let's run the test to verifvtests/Unxt/Servsces/Kiosk/Automate/meports/AskJ1minnyreportActivätyserviceTest-php --no-coverageloul nor oen ndlr Tler var wi nunbarusanCommand dockerdoster nxe ceockes /kJosk/AuPo/ape/a/ports/ASkJ1minyReportActivityServiceTest. php --no-coverageCould not open input file: /app/artisanCommand docker•cocker exec oocker vand ioash —dSid php artisan testLests unlu services Klosk Aucomaceakeporcs AskJiminnykeportAccivityservicelest.ono =-no-coverade D&l'Could not open input file: artisan• docker exec docker_lamp_1 bash -c "find / -name artisan -maxdepth 6 2>/dev/null | head -5"/home/jiminny/artisan"cd /homeiminny && php artisan test•dests/unxe/servkces/K1osk/AusomatedReports/AskJ1maynyReportActiVatyServiceTest.php --no-coverage 2>&1"PASSgetTests\Unit\Services\Kiosk\AutomatedReports\AskJiminnyReportActivityServiceTestfiltersemoty when no resultsE tatt tnt hperiod date filtersids bassess snazer fsequence number to disable first _ 0.025All 8 tests pass. Here's a summary:Root Cause & FixKoOL cause: bu1 Ldkequestraramst romsearch never set sequence number In the request params, so criterla::creater romkequest delaulted lt to 0Since isFirstRequest() returns true when sequenceNumber === 0, several implicit defaults were silently applied:ActivityDurationRange → min_duration = 1 (filters out 0-second activities)ActivityRecorded → only_recorded = 1 (restricts to recorded activities only)OrganiserGroupin → apolies user's derault croup as a tiltelThe frontend URL you noticed uses sequence_number=4, which disables these defaults - explaining why the frontend returned activities but the servicereturnee o.Fix: AskJiminnyReportActivityService.php:51 —added 'sequence_number' → 1 to the Criteria: :createFromRequest merge, ensuring isFirstRequest() returns false and no implicit defaults are injected.lest added: testbetacc1cylasPassesNonzerosequencenumberloDisablerarsckequestberaulus assers that the captured uriteria ob ect nas 1srirstRequest() === false.Öul ..Vew allliItlle wiun changesvapp/Services/Kiosk/AutomatedReports/D AskJiminnyReportActivityService.php +1 -1Reject allAccept allExap/la it to me again. Why is there issue with that+ <> Code Claude Sonnet 4.6W Windsurf Teams11T:Z0uir-o( 4 spaces...
|
PhpStorm
|
faVsco.js – ActivitySearch.php
|
NULL
|
11064
|
|
11063
|
Project: faVsco.js, menu
#11894 on JY-18909-automa Project: faVsco.js, menu
#11894 on JY-18909-automated-reports-ask-jiminny, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceT…Defaults
Run 'AskJiminnyReportActivityServiceTest.tes…uenceNumberToDisableFirstRequestDefaults'
Debug 'AskJiminnyReportActivityServiceTest.tes…uenceNumberToDisableFirstRequestDefaults'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Sync Changes
Hide This Notification
Code changed:
Hide
<?php
declare(strict_types=1);
namespace Jiminny\Component\ActivitySearch\Service;
use Illuminate\Container\Container;
use Illuminate\Support\Collection;
use Jiminny\Component\ActivitySearch\FilterDefinition;
use Jiminny\Component\ActivitySearch\FilterDefinition\AiCallScoreFilter;
use Jiminny\Component\ActivitySearch\FilterDefinition\AutoScoreFilter;
use Jiminny\Component\ActivitySearch\FilterDefinition\ClosedDealsFilter;
use Jiminny\Component\ActivitySearch\FilterDefinition\DealCloseDate;
use Jiminny\Component\ActivitySearch\FilterDefinition\HasTopicTriggersFilterDefinition;
use Jiminny\Component\ActivitySearch\FilterDefinition\PlaybackTopicFilterDefinition;
use Jiminny\Component\ActivitySearch\FilterDefinition\Security\RestrictActivityChannel;
use Jiminny\Component\ActivitySearch\FilterDefinition\Security\RestrictPublicActivitiesOnly;
use Jiminny\Component\ActivitySearch\FilterDefinition\Security\RestrictTeam;
use Jiminny\Component\ActivitySearch\FilterDefinition\Security\RestrictUserActive;
use Jiminny\Component\ActivitySearch\FilterDefinition\Security\RestrictUserGroupScope;
use Jiminny\Component\ActivitySearch\FilterDefinition\TeamInsights\TopicFilterDefinition;
use Jiminny\Component\ActivitySearch\FilterDefinitionCollection;
use Jiminny\Models\Crm\Field;
use Jiminny\Models\User;
use Jiminny\Models\Crm\Configuration;
use Jiminny\Repositories\Crm\LayoutRepository;
use Jiminny\Services\TeamService;
use Jiminny\VO\Repository\OnDemandActivitySearch\Criteria;
class ActivitySearch
{
private Container $container;
public function __construct(Container $container)
{
$this->container = $container;
}
public function getOnDemandPageFilters(): FilterDefinitionCollection
{
return FilterDefinitionCollection::make(
Collection::make([
// special case filters
FilterDefinition\ActivityStatusIn::class,
FilterDefinition\ActivityUpdatedDate::class,
FilterDefinition\ActivityRecordingStopped::class,
FilterDefinition\ActivityFilter::class,
FilterDefinition\ExternalId::class,
FilterDefinition\NudgeRunId::class,
FilterDefinition\ParticipantUserIn::class,
FilterDefinition\PartnerFilterDefinition::class,
// healthy restrictions
RestrictTeam::class,
RestrictUserGroupScope::class,
RestrictActivityChannel::class,
RestrictUserActive::class,
FilterDefinition\Security\PrivateMeetingsForCurrentUserOnly::class,
// regular filters
FilterDefinition\ActivityActualDate::class,
FilterDefinition\ActivityChannel::class,
FilterDefinition\ActivityDurationRange::class,
FilterDefinition\ActivityPlaylistIn::class,
FilterDefinition\ActivityProviderIn::class,
FilterDefinition\ActivityRecorded::class,
FilterDefinition\ActivityType::class,
FilterDefinition\CoachingFeedbackAverageScore::class,
AutoScoreFilter::class,
AiCallScoreFilter::class,
FilterDefinition\CoachingFeedbackCoachUserIn::class,
FilterDefinition\CrmFieldCollection::class,
FilterDefinition\CurrentStage::class,
FilterDefinition\Customer::class,
FilterDefinition\CustomerMonologueDuration::class,
FilterDefinition\CustomerQuestionCount::class,
FilterDefinition\DealAge::class,
DealCloseDate::class,
FilterDefinition\DealValue::class,
FilterDefinition\EngagingQuestionCount::class,
FilterDefinition\ShowInternalExternalActivitiesFilter::class,
FilterDefinition\HasTranscription::class,
FilterDefinition\InsightfulQuestionCount::class,
FilterDefinition\LanguageFilterDefinition::class,
FilterDefinition\LoggedToCrm::class,
FilterDefinition\OrganiserGroupIn:[PASSWORD]
FilterDefinition\OrganiserUserIn::class,
FilterDefinition\PatienceRange::class,
PlaybackTopicFilterDefinition::class,
FilterDefinition\ProviderFilterDefinition::class,
FilterDefinition\SortBy::class,
FilterDefinition\SpeechRate::class,
FilterDefinition\StageAtCallFilterDefinition::class,
FilterDefinition\TalkTimeRatio::class,
FilterDefinition\TeamMemberUserIn::class,
FilterDefinition\TranscriptionComposite::class,
FilterDefinition\UserMonologueDuration::class,
FilterDefinition\UserQuestionCount::class,
FilterDefinition\CommentCountRange::class,
FilterDefinition\HasPendingAiCrmNotes::class,
])
->map(fn (string $className): FilterDefinition => $this->container->make($className))
->all(),
);
}
public function getOnDemandPageFilterSet(Criteria $criteria, User $consumer): FilterDefinitionCollection
{
return $this
->getOnDemandPageFilters()
->withCriteria($criteria)
->withConsumer($consumer)
->withRestrictions($consumer->getTeam());
}
/**
* @return string[]
*/
public function getArrayFilterKeys(User $consumer): array
{
return $this
->getOnDemandPageFilters()
->withConsumer($consumer)
->getPropertyTypes([FilterDefinitionCollection::PROPERTY_TYPE_ARRAY])
->keys()
->filter(static fn (string $key): bool => ! str_contains($key, '.'))
->values()
->all();
}
private function getTeamInsightsPageFilters(bool $isExport = false): FilterDefinitionCollection
{
$dateRangeFilterClass = $isExport
? FilterDefinition\TeamInsights\ConversationExport\DateRangeFilter::class
: FilterDefinition\TeamInsights\DateRangeFilter::class;
return FilterDefinitionCollection::make(
Collection::make([
// special cases
$dateRangeFilterClass,
FilterDefinition\TeamInsights\Exists::class,
// healthy restrictions
RestrictTeam::class,
RestrictUserGroupScope::class,
RestrictActivityChannel::class,
RestrictPublicActivitiesOnly::class,
RestrictUserActive::class,
// regular filters
FilterDefinition\ActivityChannel::class,
FilterDefinition\TeamInsights\ActivityDurationRange::class,
FilterDefinition\ActivityPlaylistIn::class,
FilterDefinition\ActivityProviderIn::class,
FilterDefinition\TeamInsights\ActivityRecorded::class,
FilterDefinition\ActivityType::class,
FilterDefinition\CoachingFeedbackAverageScore::class,
AutoScoreFilter::class,
AiCallScoreFilter::class,
FilterDefinition\CoachingFeedbackCoachUserIn::class,
FilterDefinition\CrmFieldCollection::class,
FilterDefinition\Customer::class,
FilterDefinition\CurrentStage::class,
FilterDefinition\CustomerMonologueDuration::class,
FilterDefinition\CustomerQuestionCount::class,
FilterDefinition\DealAge::class,
DealCloseDate::class,
FilterDefinition\DealValue::class,
FilterDefinition\EngagingQuestionCount::class,
FilterDefinition\ShowInternalExternalActivitiesFilter::class,
FilterDefinition\InsightfulQuestionCount::class,
FilterDefinition\LanguageFilterDefinition::class,
FilterDefinition\LoggedToCrm::class,
FilterDefinition\TeamInsights\UserInFilter::class,
FilterDefinition\TeamInsights\UserGroupInFilter::class,
FilterDefinition\PatienceRange::class,
PlaybackTopicFilterDefinition::class,
FilterDefinition\ProviderFilterDefinition::class,
FilterDefinition\SortBy::class,
FilterDefinition\SpeechRate::class,
FilterDefinition\StageAtCallFilterDefinition::class,
FilterDefinition\TalkTimeRatio::class,
FilterDefinition\TeamMemberUserIn::class,
FilterDefinition\TranscriptionComposite::class,
FilterDefinition\UserMonologueDuration::class,
FilterDefinition\UserQuestionCount::class,
FilterDefinition\CommentCountRange::class,
// Relevant for topics in deals.
ClosedDealsFilter::class,
HasTopicTriggersFilterDefinition::class,
TopicFilterDefinition::class,
])
->map(fn (string $className): FilterDefinition => $this->container->make($className))
->all(),
);
}
private function getDealInsightsPageFilters(
bool $useCreatedDate = false,
bool $includeDealType = false,
bool $includePipeline = false,
): FilterDefinitionCollection {
if ($useCreatedDate) {
$periodFilterClass = FilterDefinition\DealInsights\CreatedPeriodFilter::class;
} else {
$periodFilterClass = FilterDefinition\DealInsights\ClosingPeriodFilter::class;
}
$filterSet = [
RestrictTeam::class,
$periodFilterClass,
FilterDefinition\DealInsights\UserInFilter::class,
FilterDefinition\DealInsights\UserGroupInFilter::class,
FilterDefinition\DealInsights\DealStageInFilter::class,
FilterDefinition\DealInsights\DealNameFilter::class,
];
if ($includePipeline) {
$filterSet[] = FilterDefinition\DealInsights\DealPipelineInFilter::class;
}
if ($includeDealType) {
$filterSet[] = FilterDefinition\DealInsights\DealTypeInFilter::class;
}
return FilterDefinitionCollection::make(
Collection::make($filterSet)
->map(fn (string $className): FilterDefinition => $this->container->make($className))
->all(),
);
}
public function getTeamInsightsPageFilterSet(
Criteria $criteria,
User $consumer,
bool $isExport = false
): FilterDefinitionCollection {
return $this
->getTeamInsightsPageFilters($isExport)
->withCriteria($criteria)
->withConsumer($consumer)
->withRestrictions($consumer->getTeam());
}
public function getDealInsightsPageFilterSet(
Criteria $criteria,
User $consumer
): FilterDefinitionCollection {
$includeDealType = $this->shouldIncludeDealType($consumer);
$includePipeline = $this->shouldIncludePipeline($consumer);
$useCreatedDate = $this->shouldUseCreatedDate($consumer);
return $this
->getDealInsightsPageFilters($useCreatedDate, $includeDealType, $includePipeline)
->withCriteria($criteria)
->withConsumer($consumer);
}
public function getTeamAiAutomationFilterSet(
Criteria $criteria,
User $consumer
): FilterDefinitionCollection {
return $this
->getTeamAiAutomationPageFilterSet()
->withCriteria($criteria)
->withConsumer($consumer);
}
private function getTeamAiAutomationPageFilterSet(): FilterDefinitionCollection
{
$filterSet = [
RestrictTeam::class,
FilterDefinition\DealInsights\DealStageInFilter::class,
];
return FilterDefinitionCollection::make(
Collection::make($filterSet)
->map(fn (string $className): FilterDefinition => $this->container->make($className))
->all(),
);
}
public function getHomepageFilterSet(Criteria $criteria, User $consumer): FilterDefinitionCollection
{
$filterDefinitionCollection = FilterDefinitionCollection::make(
Collection::make([
RestrictTeam::class,
RestrictUserGroupScope::class,
RestrictActivityChannel::class,
RestrictUserActive::class,
FilterDefinition\Security\PrivateMeetingsForCurrentUserOnly::class,
FilterDefinition\ActivityActualDate::class,
FilterDefinition\Customer::class,
FilterDefinition\ActivityChannel::class,
FilterDefinition\ActivityDurationRange::class,
FilterDefinition\ActivityProviderIn::class,
FilterDefinition\ActivityRecorded::class,
FilterDefinition\ActivityRecordingStopped::class,
FilterDefinition\ActivityScheduledDate::class,
FilterDefinition\ActivityStatusIn::class,
FilterDefinition\LoggedToCrm::class,
FilterDefinition\OrganiserUserIn::class,
FilterDefinition\OrganiserUserNotIn::class,
FilterDefinition\ProviderFilterDefinition::class,
FilterDefinition\SortBy::class,
FilterDefinition\UserGroupInOptionalFilter::class,
FilterDefinition\OnlyActiveUsers::class,
])
->map(fn (string $className): FilterDefinition => $this->container->make($className))
->all(),
);
$filterDefinitionCollection->withCriteria($criteria);
$filterDefinitionCollection->withConsumer($consumer);
return $filterDefinitionCollection;
}
public function getPartnerFilterSet(Criteria $criteria): FilterDefinitionCollection
{
$filterDefinitionCollection = FilterDefinitionCollection::make(
Collection::make([
RestrictActivityChannel::class,
FilterDefinition\OrganiserTeamIn::class,
FilterDefinition\ActivityUpdatedDate::class,
FilterDefinition\ActivityStatusIn::class,
FilterDefinition\SortBy::class,
])
->map(fn (string $className): FilterDefinition => $this->container->make($className))
->all()
);
$filterDefinitionCollection->withCriteria($criteria);
return $filterDefinitionCollection;
}
private function shouldIncludeDealType(User $user): bool
{
$crmConfig = $user->getTeam()->getCrmConfiguration();
$crmProviderName = $crmConfig->getProviderName();
if (! array_key_exists($crmProviderName, Field::BUSINESS_TYPE_FIELDS)) {
return false;
}
$layoutRepository = app(LayoutRepository::class);
$layoutFields = $layoutRepository->getDealInsightLayoutFields($crmConfig);
$dealTypeField = Field::BUSINESS_TYPE_FIELDS[$crmProviderName];
if (! in_array($dealTypeField, $layoutFields)) {
return false;
}
return true;
}
private function shouldIncludePipeline(User $user): bool
{
$crmConfig = $user->getTeam()->getCrmConfiguration();
$crmProviderName = $crmConfig->getProviderName();
if (in_array($crmProviderName, [
Configuration::PROVIDER_SALESFORCE,
Configuration::PROVIDER_INTEGRATION_APP,
])) {
return false;
}
return true;
}
private function shouldUseCreatedDate(User $user): bool
{
$teamService = app(TeamService::class);
return ! $teamService->useDealInsightsClosedDateFilter($user->getTeam());
}
}...
|
PhpStorm
|
faVsco.js – ActivitySearch.php
|
NULL
|
11063
|
|
11062
|
PhpStormFileEditViewNavigateCodeLaravelRefactorFV PhpStormFileEditViewNavigateCodeLaravelRefactorFV faVsco.s v#11894 on JY-18909-automated-reports-ask-iminny K vProject v© ReportController.phpToolsWindowHelpyJiminnyDeouecommana.ongv Service© ActivityApiSearch.ph© ActivitySearch.php© UserOptionsByGrour© AbstractStageFilterDefilActivitySearchServicePrC DeallnsightsPeriodFilter0 DealinsidnisPeriodrilteng FilterDetinition.phpc rterverntoncolecto© FilterDefinitionQuery.ph© FilterDefinitionQueryCol• FilteredValueContainerli© IntMinMaxRange.php[ AiActivityType[ AiAutomationD AiCallScoringD AskAnythingD AskJiminnyAiDAWSM BillinaManagementM Cache• CoachingFeedback> D CountryD CustomerApi• DatabaseC DatadogC DateTimeDeallnsights_ DealRisksEasticsearch>_tloquent> DEncoding> D EncryptionDESD Faker• FeatureFlagsD FFMpeg• FileSystemD GeckoD GongGuzzleHttpKeyPoints• KioskM LanquageDetectionLiveFeedD Locks• Math• MediaPipeline• MeetingBot• MobileSettings| ModelNotiticationNudgeParagraphBreakerM ParticipantSpeechPartitionedCookieD PlaybackPagePlaylistThrssl-dAulomaleakeporscommand.ono© AutomatedReportsSendCommand.phpAddLayoutEntities.php© Team.php© AutomatedReportsRepository.php X© AutomatedReportsService.phpC CreateHeldActivityEvent.php= custom.log= laravel.logA SF [jiminny@localhost]A HS_local [jiminny@localhost]A console [PROD]< console LUlconsole SlAGiNG© AskJiminnyReportActivityService.php© ActivitySearch.php x© FilterDefinitionCollection.php© Criteria.php© AskJiminnyReportActivityServiceTest.phpRequestGenerateAskJiminnyReportJobTest.phpsrono(e TrackProvidernstallled-vent.onodeclare(strict_types=1);© CreateActivityLoggedEvent.php(©) ActivityLogged.php© UserPilotActivityListener.php(C) AutomatedReportsCallbackService.phpnamespace Jiminny\Component\ActivitySearch\Service;© RequestGenerateAskJiminnyReportJob.phpRequestGenerateReportJob.php© AutomatedReportResult.php(C) AutomatedReport.phpclass Automacedкeрortskepo o:815 X4 л› use ...class ActivitvSearch591141151161171181191201211124123lests passed: (a minute ago/*** Retrieve all standard (non-Ask Jiminny) M* @param string $sortColumnIne column tc-oe* Oparam string $sortDirection The sort dire 107-108*orerurn cocuectonsauromareonedor10912 usagespublic function getAllStandardReports(string $sortColumn = 'created_at',string $sortDirection = 'desc'): Collection {...}/**114113114115116117* Retrieve all Ask Liminny reports created 2118* OodrdllusernusenThe user whos 119* @param string $sortColumnThe column tc 130* Oparam string $sortDirection The sort dire1151* Oreturn Collection<AutomatedReport>1Y114 usagespublic function getAskJiminnyReportsByUser(199User $user,-200string $sortColumn = 'created_at',string ssorcbirection = "desc"202): Collection {...J232253Z usages/**1254private function buildSortedQuery(string $sor235250237* Get all active and enabled reports with ac244245* @param string $frequency246247* dreturh coLcectzon<aucomacedкeрort>24825823 usagespublic function getActiveReportsByFrequency(:2597 usagesprivate Container $container;public function __construct(Container $container)f...}public function getOnDemandPageFilters(): FilterDefinitionCollectionf...}public function getOnDemandPageFilterSet(Criteria $criteria, User Sconsumer): FilterDefinitreturn $this->getOnDemandPageFilters()->nunenainchuerlay->withConsumer ($consumer)->withRestrictions($consumer->getTeam()):9 usagespublic function getArrayFilterKeys(User $consumer): arrayf..31 usageprivate function getTeamInsightsPageFilters(bool $isExport = false): FilterDefinitionCollecprivate function getDealInsightsPageFilters(bool $useCreatedDate = false,bool $includeDealType = false,bool $includePipeline = false,): FilterDefinitionCollection {.+public function getTeamInsightsPageFilterSet(cricerta pcracerta,user +consumer,bool sisExport = false): FilterDefinitionCollection {...public function getDealInsightsPageFilterSet(Criteria $criteria,User $consumer): FalterDefinitionCollection{..1 usagepubLic tunccion getleamAlAucomationriltersectSupport Daily • in 2 h 50 mAAskJiminnyReportActivityServiceT…Defaults100% C•Tue 14 Apr 12:10:31CascadeFixing ReportControllerAutomated Report MarFixing Ask Jiminny Rep+D ...Now let's run the test to verifvtests/Unxt/Servsces/Kiosk/Automate/meports/AskJ1minnyreportActivätyserviceTest-php --no-coverageloul nor oen ndlr Tler var wi nunbarusanCommand dockerdoster nxe ceockes /kJosk/AuPo/ape/a/ports/ASkJ1minyReportActivityServiceTest. php --no-coverageCould not open input file: /app/artisanCommand docker•cocker exec oocker land ioash —dSid php artisan testLests unlu services Klosk Aucomaceakeporcs AskJiminnykeportAccivityservicelest.ono =-no-coverade D&l'Could not open input file: artisan• docker exec docker_lamp_1 bash -c "find / -name artisan -maxdepth 6 2>/dev/null | head -5"/home/jiminny/artisan"cd /homeiminny && php artisan test•dests/unxe/servkces/K1osk/AusomatedReports/AskJ1maynyReportActiVatyServiceTest.php --no-coverage 2>&1"PASSgetTests\Unit\Services\Kiosk\AutomatedReports\AskJiminnyReportActivityServiceTesta fittersemoty when no resultsE tatt tnt hperiod date filtersids bassess snazer fsequence number to disable first _ 0.025All 8 tests pass. Here's a summary:Root Cause & FixKoOL cause: bu1 Ldkequestraramst romsearch never set sequence number In the request params, so criterla::creater romkequest delaulted lt to 0Since isFirstRequest() returns true when sequenceNumber === 0, several implicit defaults were silently applied:ActivityDurationRange → min_duration = 1 (filters out 0-second activities)ActivityRecorded → only_recorded = 1 (restricts to recorded activities only)OrganiserGroupin → apolies user's derault croup as a tilterThe frontend URL you noticed uses sequence_number=4, which disables these defaults - explaining why the frontend returned activities but the servicereturnee o.Fix: AskJiminnyReportActivityService.php:51 —added 'sequence_number' → 1 to the Criteria: :createFromRequest merge, ensuring isFirstRequest() returns false and no implicit defaults are injected.lest added: testbetacc1cylasPassesNonzerosequencenumberloDisablerarsckequestberaulus assers that the captured uriteria ob ect nas 1srirstRequest() === false.Öul ..Vew allliItlle win changesvapp/Services/Kiosk/AutomatedReports/ [ AskJiminnyReportActivityService.php +1 -1Reject allAccept allAsk anything (2*L)+ <> Code Claude Sonnet 4.6W Windsurf Teams11T:Z0uir-o( 4 spaces...
|
NULL
|
NULL
|
NULL
|
11062
|
|
11061
|
+SlackEDHomeDMSActivityFilesLater..•More+FileEditV +SlackEDHomeDMSActivityFilesLater..•More+FileEditViewGoHistoryWindowHelpJiminny ...# Starredplatform-inner-teamChannels# ai-chapter# alerts# backend# confusion-clinic# curiosity_lab# engineering# frontend# general# infra-changes# jiminny-bg# platform-tickets# product_launches# random# releases# sofia-office# support# thank-yous# the_people_of jimi…..Direct messagesAneliya Angelova, ...Steliyan GeorgievAdelina Petrova, Ili.... Adelina PetrovaO. Calea Dimitravo→Search Jiminny IncAneliya Angelova, Nikolay Yankov, Steliyan GeorgievMessagesAdd canvas+Nikolay Yankov 10:45 AMпиши кат оя рьннешLukas Kovalik 10:52 AMзабавих се че ми се разбазикаха settings за средипуснах и мина и fail-наима result но e failedзначиREASON_NOT_ENOUGH_ACTIVITIESвиж дали има нещо в OD със този филтьрNikolay Yankov 11:01 AMДобреNikolay Yankov 11:39 AMя рьнни пак LukasLukas Kovalik 11:43 AMготовосьщотоCompetitive pitches беше втория нали такаNikolay Yankov 12:04 PMДа, там има 14 активитита, защо не сработи този пьт?Lukas Kovalik 12:05 PMпак изглежда sequenceгледам гоMessage Aneliya Angelova, Nikolay Yankov, Steliyan Georgiev+Aa> 0ladl= Support Daily • in 2h 50 m100% <47Tue 14 Apr 12:10:3186 0Today ~...
|
NULL
|
NULL
|
NULL
|
11061
|
|
11060
|
Project: faVsco.js, menu
#11894 on JY-18909-automa Project: faVsco.js, menu
#11894 on JY-18909-automated-reports-ask-jiminny, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceT…Defaults
Run 'AskJiminnyReportActivityServiceTest.tes…uenceNumberToDisableFirstRequestDefaults'
Debug 'AskJiminnyReportActivityServiceTest.tes…uenceNumberToDisableFirstRequestDefaults'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Sync Changes
Hide This Notification
Code changed:
Hide
<?php
declare(strict_types=1);
namespace Jiminny\Component\ActivitySearch\Service;
use Illuminate\Container\Container;
use Illuminate\Support\Collection;
use Jiminny\Component\ActivitySearch\FilterDefinition;
use Jiminny\Component\ActivitySearch\FilterDefinition\AiCallScoreFilter;
use Jiminny\Component\ActivitySearch\FilterDefinition\AutoScoreFilter;
use Jiminny\Component\ActivitySearch\FilterDefinition\ClosedDealsFilter;
use Jiminny\Component\ActivitySearch\FilterDefinition\DealCloseDate;
use Jiminny\Component\ActivitySearch\FilterDefinition\HasTopicTriggersFilterDefinition;
use Jiminny\Component\ActivitySearch\FilterDefinition\PlaybackTopicFilterDefinition;
use Jiminny\Component\ActivitySearch\FilterDefinition\Security\RestrictActivityChannel;
use Jiminny\Component\ActivitySearch\FilterDefinition\Security\RestrictPublicActivitiesOnly;
use Jiminny\Component\ActivitySearch\FilterDefinition\Security\RestrictTeam;
use Jiminny\Component\ActivitySearch\FilterDefinition\Security\RestrictUserActive;
use Jiminny\Component\ActivitySearch\FilterDefinition\Security\RestrictUserGroupScope;
use Jiminny\Component\ActivitySearch\FilterDefinition\TeamInsights\TopicFilterDefinition;
use Jiminny\Component\ActivitySearch\FilterDefinitionCollection;
use Jiminny\Models\Crm\Field;
use Jiminny\Models\User;
use Jiminny\Models\Crm\Configuration;
use Jiminny\Repositories\Crm\LayoutRepository;
use Jiminny\Services\TeamService;
use Jiminny\VO\Repository\OnDemandActivitySearch\Criteria;
class ActivitySearch
{
private Container $container;
public function __construct(Container $container)
{
$this->container = $container;
}
public function getOnDemandPageFilters(): FilterDefinitionCollection
{
return FilterDefinitionCollection::make(
Collection::make([
// special case filters
FilterDefinition\ActivityStatusIn::class,
FilterDefinition\ActivityUpdatedDate::class,
FilterDefinition\ActivityRecordingStopped::class,
FilterDefinition\ActivityFilter::class,
FilterDefinition\ExternalId::class,
FilterDefinition\NudgeRunId::class,
FilterDefinition\ParticipantUserIn::class,
FilterDefinition\PartnerFilterDefinition::class,
// healthy restrictions
RestrictTeam::class,
RestrictUserGroupScope::class,
RestrictActivityChannel::class,
RestrictUserActive::class,
FilterDefinition\Security\PrivateMeetingsForCurrentUserOnly::class,
// regular filters
FilterDefinition\ActivityActualDate::class,
FilterDefinition\ActivityChannel::class,
FilterDefinition\ActivityDurationRange::class,
FilterDefinition\ActivityPlaylistIn::class,
FilterDefinition\ActivityProviderIn::class,
FilterDefinition\ActivityRecorded::class,
FilterDefinition\ActivityType::class,
FilterDefinition\CoachingFeedbackAverageScore::class,
AutoScoreFilter::class,
AiCallScoreFilter::class,
FilterDefinition\CoachingFeedbackCoachUserIn::class,
FilterDefinition\CrmFieldCollection::class,
FilterDefinition\CurrentStage::class,
FilterDefinition\Customer::class,
FilterDefinition\CustomerMonologueDuration::class,
FilterDefinition\CustomerQuestionCount::class,
FilterDefinition\DealAge::class,
DealCloseDate::class,
FilterDefinition\DealValue::class,
FilterDefinition\EngagingQuestionCount::class,
FilterDefinition\ShowInternalExternalActivitiesFilter::class,
FilterDefinition\HasTranscription::class,
FilterDefinition\InsightfulQuestionCount::class,
FilterDefinition\LanguageFilterDefinition::class,
FilterDefinition\LoggedToCrm::class,
FilterDefinition\OrganiserGroupIn:[PASSWORD]
FilterDefinition\OrganiserUserIn::class,
FilterDefinition\PatienceRange::class,
PlaybackTopicFilterDefinition::class,
FilterDefinition\ProviderFilterDefinition::class,
FilterDefinition\SortBy::class,
FilterDefinition\SpeechRate::class,
FilterDefinition\StageAtCallFilterDefinition::class,
FilterDefinition\TalkTimeRatio::class,
FilterDefinition\TeamMemberUserIn::class,
FilterDefinition\TranscriptionComposite::class,
FilterDefinition\UserMonologueDuration::class,
FilterDefinition\UserQuestionCount::class,
FilterDefinition\CommentCountRange::class,
FilterDefinition\HasPendingAiCrmNotes::class,
])
->map(fn (string $className): FilterDefinition => $this->container->make($className))
->all(),
);
}
public function getOnDemandPageFilterSet(Criteria $criteria, User $consumer): FilterDefinitionCollection
{
return $this
->getOnDemandPageFilters()
->withCriteria($criteria)
->withConsumer($consumer)
->withRestrictions($consumer->getTeam());
}
/**
* @return string[]
*/
public function getArrayFilterKeys(User $consumer): array
{
return $this
->getOnDemandPageFilters()
->withConsumer($consumer)
->getPropertyTypes([FilterDefinitionCollection::PROPERTY_TYPE_ARRAY])
->keys()
->filter(static fn (string $key): bool => ! str_contains($key, '.'))
->values()
->all();
}
private function getTeamInsightsPageFilters(bool $isExport = false): FilterDefinitionCollection
{
$dateRangeFilterClass = $isExport
? FilterDefinition\TeamInsights\ConversationExport\DateRangeFilter::class
: FilterDefinition\TeamInsights\DateRangeFilter::class;
return FilterDefinitionCollection::make(
Collection::make([
// special cases
$dateRangeFilterClass,
FilterDefinition\TeamInsights\Exists::class,
// healthy restrictions
RestrictTeam::class,
RestrictUserGroupScope::class,
RestrictActivityChannel::class,
RestrictPublicActivitiesOnly::class,
RestrictUserActive::class,
// regular filters
FilterDefinition\ActivityChannel::class,
FilterDefinition\TeamInsights\ActivityDurationRange::class,
FilterDefinition\ActivityPlaylistIn::class,
FilterDefinition\ActivityProviderIn::class,
FilterDefinition\TeamInsights\ActivityRecorded::class,
FilterDefinition\ActivityType::class,
FilterDefinition\CoachingFeedbackAverageScore::class,
AutoScoreFilter::class,
AiCallScoreFilter::class,
FilterDefinition\CoachingFeedbackCoachUserIn::class,
FilterDefinition\CrmFieldCollection::class,
FilterDefinition\Customer::class,
FilterDefinition\CurrentStage::class,
FilterDefinition\CustomerMonologueDuration::class,
FilterDefinition\CustomerQuestionCount::class,
FilterDefinition\DealAge::class,
DealCloseDate::class,
FilterDefinition\DealValue::class,
FilterDefinition\EngagingQuestionCount::class,
FilterDefinition\ShowInternalExternalActivitiesFilter::class,
FilterDefinition\InsightfulQuestionCount::class,
FilterDefinition\LanguageFilterDefinition::class,
FilterDefinition\LoggedToCrm::class,
FilterDefinition\TeamInsights\UserInFilter::class,
FilterDefinition\TeamInsights\UserGroupInFilter::class,
FilterDefinition\PatienceRange::class,
PlaybackTopicFilterDefinition::class,
FilterDefinition\ProviderFilterDefinition::class,
FilterDefinition\SortBy::class,
FilterDefinition\SpeechRate::class,
FilterDefinition\StageAtCallFilterDefinition::class,
FilterDefinition\TalkTimeRatio::class,
FilterDefinition\TeamMemberUserIn::class,
FilterDefinition\TranscriptionComposite::class,
FilterDefinition\UserMonologueDuration::class,
FilterDefinition\UserQuestionCount::class,
FilterDefinition\CommentCountRange::class,
// Relevant for topics in deals.
ClosedDealsFilter::class,
HasTopicTriggersFilterDefinition::class,
TopicFilterDefinition::class,
])
->map(fn (string $className): FilterDefinition => $this->container->make($className))
->all(),
);
}
private function getDealInsightsPageFilters(
bool $useCreatedDate = false,
bool $includeDealType = false,
bool $includePipeline = false,
): FilterDefinitionCollection {
if ($useCreatedDate) {
$periodFilterClass = FilterDefinition\DealInsights\CreatedPeriodFilter::class;
} else {
$periodFilterClass = FilterDefinition\DealInsights\ClosingPeriodFilter::class;
}
$filterSet = [
RestrictTeam::class,
$periodFilterClass,
FilterDefinition\DealInsights\UserInFilter::class,
FilterDefinition\DealInsights\UserGroupInFilter::class,
FilterDefinition\DealInsights\DealStageInFilter::class,
FilterDefinition\DealInsights\DealNameFilter::class,
];
if ($includePipeline) {
$filterSet[] = FilterDefinition\DealInsights\DealPipelineInFilter::class;
}
if ($includeDealType) {
$filterSet[] = FilterDefinition\DealInsights\DealTypeInFilter::class;
}
return FilterDefinitionCollection::make(
Collection::make($filterSet)
->map(fn (string $className): FilterDefinition => $this->container->make($className))
->all(),
);
}
public function getTeamInsightsPageFilterSet(
Criteria $criteria,
User $consumer,
bool $isExport = false
): FilterDefinitionCollection {
return $this
->getTeamInsightsPageFilters($isExport)
->withCriteria($criteria)
->withConsumer($consumer)
->withRestrictions($consumer->getTeam());
}
public function getDealInsightsPageFilterSet(
Criteria $criteria,
User $consumer
): FilterDefinitionCollection {
$includeDealType = $this->shouldIncludeDealType($consumer);
$includePipeline = $this->shouldIncludePipeline($consumer);
$useCreatedDate = $this->shouldUseCreatedDate($consumer);
return $this
->getDealInsightsPageFilters($useCreatedDate, $includeDealType, $includePipeline)
->withCriteria($criteria)
->withConsumer($consumer);
}
public function getTeamAiAutomationFilterSet(
Criteria $criteria,
User $consumer
): FilterDefinitionCollection {
return $this
->getTeamAiAutomationPageFilterSet()
->withCriteria($criteria)
->withConsumer($consumer);
}
private function getTeamAiAutomationPageFilterSet(): FilterDefinitionCollection
{
$filterSet = [
RestrictTeam::class,
FilterDefinition\DealInsights\DealStageInFilter::class,
];
return FilterDefinitionCollection::make(
Collection::make($filterSet)
->map(fn (string $className): FilterDefinition => $this->container->make($className))
->all(),
);
}
public function getHomepageFilterSet(Criteria $criteria, User $consumer): FilterDefinitionCollection
{
$filterDefinitionCollection = FilterDefinitionCollection::make(
Collection::make([
RestrictTeam::class,
RestrictUserGroupScope::class,
RestrictActivityChannel::class,
RestrictUserActive::class,
FilterDefinition\Security\PrivateMeetingsForCurrentUserOnly::class,
FilterDefinition\ActivityActualDate::class,
FilterDefinition\Customer::class,
FilterDefinition\ActivityChannel::class,
FilterDefinition\ActivityDurationRange::class,
FilterDefinition\ActivityProviderIn::class,
FilterDefinition\ActivityRecorded::class,
FilterDefinition\ActivityRecordingStopped::class,
FilterDefinition\ActivityScheduledDate::class,
FilterDefinition\ActivityStatusIn::class,
FilterDefinition\LoggedToCrm::class,
FilterDefinition\OrganiserUserIn::class,
FilterDefinition\OrganiserUserNotIn::class,
FilterDefinition\ProviderFilterDefinition::class,
FilterDefinition\SortBy::class,
FilterDefinition\UserGroupInOptionalFilter::class,
FilterDefinition\OnlyActiveUsers::class,
])
->map(fn (string $className): FilterDefinition => $this->container->make($className))
->all(),
);
$filterDefinitionCollection->withCriteria($criteria);
$filterDefinitionCollection->withConsumer($consumer);
return $filterDefinitionCollection;
}
public function getPartnerFilterSet(Criteria $criteria): FilterDefinitionCollection
{
$filterDefinitionCollection = FilterDefinitionCollection::make(
Collection::make([
RestrictActivityChannel::class,
FilterDefinition\OrganiserTeamIn::class,
FilterDefinition\ActivityUpdatedDate::class,
FilterDefinition\ActivityStatusIn::class,
FilterDefinition\SortBy::class,
])
->map(fn (string $className): FilterDefinition => $this->container->make($className))
->all()
);
$filterDefinitionCollection->withCriteria($criteria);
return $filterDefinitionCollection;
}
private function shouldIncludeDealType(User $user): bool
{
$crmConfig = $user->getTeam()->getCrmConfiguration();
$crmProviderName = $crmConfig->getProviderName();
if (! array_key_exists($crmProviderName, Field::BUSINESS_TYPE_FIELDS)) {
return false;
}
$layoutRepository = app(LayoutRepository::class);
$layoutFields = $layoutRepository->getDealInsightLayoutFields($crmConfig);
$dealTypeField = Field::BUSINESS_TYPE_FIELDS[$crmProviderName];
if (! in_array($dealTypeField, $layoutFields)) {
return false;
}
return true;
}
private function shouldIncludePipeline(User $user): bool
{
$crmConfig = $user->getTeam()->getCrmConfiguration();
$crmProviderName = $crmConfig->getProviderName();
if (in_array($crmProviderName, [
Configuration::PROVIDER_SALESFORCE,
Configuration::PROVIDER_INTEGRATION_APP,
])) {
return false;
}
return true;
}
private function shouldUseCreatedDate(User $user): bool
{
$teamService = app(TeamService::class);
return ! $teamService->useDealInsightsClosedDateFilter($user->getTeam());
}
}
Sync Changes
Hide This Notification
Code changed:
Hide
15
4
Previous Highlighted Error
Next Highlighted Error
<?php
declare(strict_types=1);
namespace Jiminny\Repositories;
use Carbon\CarbonImmutable;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Support\Carbon;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Pagination\LengthAwarePaginator;
use Illuminate\Support\Facades\DB;
use Jiminny\Models\AutomatedReport;
use Jiminny\Models\AutomatedReportResult;
use Jiminny\Models\Team;
use Jiminny\Models\User;
use Jiminny\Services\Kiosk\AutomatedReports\AutomatedReportsService;
use Jiminny\Services\Kiosk\AutomatedReports\ReportSort;
use Jiminny\Services\Kiosk\AutomatedReports\ReportSortDirection;
class AutomatedReportsRepository
{
/**
* Create a new automated report
*
* @param array $data
*
* @return AutomatedReport
*/
public function create(array $data): AutomatedReport
{
return AutomatedReport::create($data);
}
/**
* Find an automated report by UUID
*
* @param string $uuid
*
* @return AutomatedReport|null
*/
public function findByUuid(string $uuid): ?AutomatedReport
{
return AutomatedReport::where('uuid', AutomatedReport::toOptimized($uuid))->first();
}
public function findByIdOrUuid(string $idOrUuid): ?AutomatedReport
{
if (is_numeric($idOrUuid)) {
return AutomatedReport::find((int) $idOrUuid);
}
return AutomatedReport::where('uuid', AutomatedReport::toOptimized($idOrUuid))->first();
}
/**
* Retrieve all standard (non-Ask Jiminny) automated reports.
*
* @param string $sortColumn The column to sort by. Allowed values: 'created_by', 'created_at'. Defaults to 'created_at'.
* @param string $sortDirection The sort direction. Allowed values: 'asc', 'desc'. Defaults to 'desc'.
*
* @return Collection<AutomatedReport>
*/
public function getAllStandardReports(
string $sortColumn = 'created_at',
string $sortDirection = 'desc'
): Collection {
return $this->buildSortedQuery($sortColumn, $sortDirection)
->whereNot('type', AutomatedReportsService::TYPE_ASK_JIMINNY)
->get();
}
/**
* Retrieve all Ask Jiminny reports created by the given user.
*
* @param User $user The user whose reports to retrieve.
* @param string $sortColumn The column to sort by. Allowed values: 'created_by', 'created_at'. Defaults to 'created_at'.
* @param string $sortDirection The sort direction. Allowed values: 'asc', 'desc'. Defaults to 'desc'.
*
* @return Collection<AutomatedReport>
*/
public function getAskJiminnyReportsByUser(
User $user,
string $sortColumn = 'created_at',
string $sortDirection = 'desc'
): Collection {
return $this->buildSortedQuery($sortColumn, $sortDirection)
->where('type', AutomatedReportsService::TYPE_ASK_JIMINNY)
->where('created_by', $user->getId())
->get();
}
private function buildSortedQuery(string $sortColumn, string $sortDirection): \Illuminate\Database\Eloquent\Builder
{
$allowedColumns = ['created_by', 'created_at'];
if (! in_array($sortColumn, $allowedColumns)) {
$sortColumn = 'created_at';
}
$sortDirection = strtolower($sortDirection) === 'asc' ? 'asc' : 'desc';
$query = AutomatedReport::query()->with(['creator', 'team']);
if ($sortColumn === 'created_by') {
$query->leftJoin('users', 'users.id', '=', 'automated_reports.created_by')
->orderByRaw("users.name COLLATE utf8mb4_unicode_ci {$sortDirection}")
->select('automated_reports.*');
} else {
$query->orderBy($sortColumn, $sortDirection);
}
return $query;
}
/**
* Get all active and enabled reports with active teams for the specified frequency.
*
* @param string $frequency
*
* @return Collection<AutomatedReport>
*/
public function getActiveReportsByFrequency(string $frequency): Collection
{
return AutomatedReport::where('automated_reports.status', true)
->where('automated_reports.frequency', $frequency)
->join('teams', 'automated_reports.team_id', '=', 'teams.id')
->where('teams.status', Team::STATUS_ACTIVE)
->where(function ($query) {
$query->whereNull('automated_reports.expires_at')
->orWhere('automated_reports.expires_at', '>=', now()->toDateString());
})
->select('automated_reports.*')
->get();
}
/**
* Update an automated report
*
* @param AutomatedReport $report
* @param array $data
*
* @return AutomatedReport
*/
public function update(AutomatedReport $report, array $data): AutomatedReport
{
$report->update($data);
return $report;
}
/**
* Create a new automated report result.
*
* @param array $data The data to create the automated report result with.
*
* @return AutomatedReportResult The newly created automated report result.
*/
public function createResult(array $data): AutomatedReportResult
{
return AutomatedReportResult::create($data);
}
/**
* Find an automated report result by UUID.
*
* @param string $uuid The UUID to find the automated report result with.
*
* @return AutomatedReportResult|null The automated report result if found, otherwise null.
*/
public function findResultByUuid(string $uuid): ?AutomatedReportResult
{
return AutomatedReportResult::where('uuid', AutomatedReportResult::toOptimized($uuid))->first();
}
public function findResultByUuidForUser(string $uuid, User $user): ?AutomatedReportResult
{
return AutomatedReportResult::query()
->where('uuid', AutomatedReportResult::toOptimized($uuid))
->whereHas('report', static function ($query) use ($user): void {
$query->where('team_id', $user->getTeamId())
->where('created_by', $user->getId());
})
->first();
}
public function findChildResult(AutomatedReportResult $result, string $type): ?AutomatedReportResult
{
return AutomatedReportResult::query()
->where('parent_id', $result->getId())
->where('media_type', $type)
->first();
}
public function getGeneratedNotSentResults(): Collection
{
return AutomatedReportResult::query()
->whereNotNull('generated_at')
->whereNull('sent_at')
->where('status', AutomatedReportResult::STATUS_GENERATED)
->whereHas('report')
->with('report')
->get();
}
public function getPaginatedUserReports(
User $user,
ReportSort $sort,
ReportSortDirection $sortDirection,
int $resultsPerPage,
int $page,
?Carbon $fromDate,
?Carbon $toDate,
array $teamIds,
array $reportTypes,
?string $name,
): LengthAwarePaginator {
$query = AutomatedReportResult::query()
->whereNotNull('automated_report_results.generated_at')
->join('automated_reports', 'automated_report_results.report_id', '=', 'automated_reports.id')
->where('automated_reports.team_id', $user->getTeamId())
->whereJsonContains('automated_reports.recipients->users', $user->getId())
->orderByRaw("$sort->value COLLATE utf8mb4_unicode_ci {$sortDirection->value}")
->select('automated_report_results.*')
->with('report.team');
if ($fromDate !== null && $toDate !== null) {
$query->whereBetween('generated_at', [$fromDate, $toDate]);
}
if (! empty($teamIds)) {
$query->where(function ($q) use ($teamIds) {
foreach ($teamIds as $id) {
$q->orWhereJsonContains('automated_reports.groups', $id);
}
});
}
if (! empty($reportTypes)) {
$query->whereIn('automated_reports.type', $reportTypes);
}
if (! empty($name)) {
$query->whereLike('name', "%$name%");
}
return $query->paginate($resultsPerPage, ['*'], 'page', $page);
}
public function countUserReports(User $user): int
{
return AutomatedReportResult::query()
->whereNotNull('generated_at')
->whereNotNull('sent_at')
->whereHas('report', function ($q) use ($user) {
$q->where('team_id', $user->getTeamId())
->whereJsonContains('recipients->users', $user->getId());
})
->count();
}
/**
* Get report IDs for a specific team
*
* @param Team $team
*
* @return \Illuminate\Support\Collection
*/
public function getReportIdsByTeam(Team $team): \Illuminate\Support\Collection
{
return AutomatedReport::where('team_id', $team->getId())->pluck('id');
}
/**
* Get all reports for a specific team
*
* @param Team $team
*
* @return Collection
*/
public function getReportsByTeam(Team $team): Collection
{
return AutomatedReport::where('team_id', $team->getId())->get();
}
/**
* Get all report results for a specific report
*
* @param AutomatedReport $report
*
* @return Collection
*/
public function getResultsByReport(AutomatedReport $report): Collection
{
return $this->getResultsByReportQuery($report)->get();
}
public function getResultsByReportQuery(AutomatedReport $report): Builder
{
return AutomatedReportResult::where('report_id', $report->getId());
}
public function getReportResultsQueryForRetention(Team $team, CarbonImmutable $retentionDate): Builder
{
$reportIds = $this->getReportIdsByTeam($team);
return AutomatedReportResult::query()->whereIn('report_id', $reportIds)
->whereRaw('IFNULL(generated_at, created_at) <= ?', [$retentionDate]);
}
/**
* @param int|null $teamId Optional team ID to filter results
*
* @return \Illuminate\Support\Collection<int, int> Collection of team IDs
*/
public function getTeamIdsWithReportsResults(?int $teamId = null): \Illuminate\Support\Collection
{
$query = DB::table('automated_reports')
->join('teams', 'automated_reports.team_id', '=', 'teams.id')
->select('teams.id')
->distinct();
if ($teamId !== null) {
$query->where('teams.id', $teamId);
}
return $query->pluck('teams.id');
}
}
Project
Project
New File or Directory…
Expand Selected
Collapse All
Options
Hide...
|
PhpStorm
|
faVsco.js – ActivitySearch.php
|
NULL
|
11060
|
|
11059
|
Project: faVsco.js, menu
#11894 on JY-18909-automa Project: faVsco.js, menu
#11894 on JY-18909-automated-reports-ask-jiminny, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceT…Defaults
Run 'AskJiminnyReportActivityServiceTest.tes…uenceNumberToDisableFirstRequestDefaults'
Debug 'AskJiminnyReportActivityServiceTest.tes…uenceNumberToDisableFirstRequestDefaults'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Sync Changes
Hide This Notification
Code changed:
Hide
<?php
declare(strict_types=1);
namespace Jiminny\Component\ActivitySearch\Service;
use Illuminate\Container\Container;
use Illuminate\Support\Collection;
use Jiminny\Component\ActivitySearch\FilterDefinition;
use Jiminny\Component\ActivitySearch\FilterDefinition\AiCallScoreFilter;
use Jiminny\Component\ActivitySearch\FilterDefinition\AutoScoreFilter;
use Jiminny\Component\ActivitySearch\FilterDefinition\ClosedDealsFilter;
use Jiminny\Component\ActivitySearch\FilterDefinition\DealCloseDate;
use Jiminny\Component\ActivitySearch\FilterDefinition\HasTopicTriggersFilterDefinition;
use Jiminny\Component\ActivitySearch\FilterDefinition\PlaybackTopicFilterDefinition;
use Jiminny\Component\ActivitySearch\FilterDefinition\Security\RestrictActivityChannel;
use Jiminny\Component\ActivitySearch\FilterDefinition\Security\RestrictPublicActivitiesOnly;
use Jiminny\Component\ActivitySearch\FilterDefinition\Security\RestrictTeam;
use Jiminny\Component\ActivitySearch\FilterDefinition\Security\RestrictUserActive;
use Jiminny\Component\ActivitySearch\FilterDefinition\Security\RestrictUserGroupScope;
use Jiminny\Component\ActivitySearch\FilterDefinition\TeamInsights\TopicFilterDefinition;
use Jiminny\Component\ActivitySearch\FilterDefinitionCollection;
use Jiminny\Models\Crm\Field;
use Jiminny\Models\User;
use Jiminny\Models\Crm\Configuration;
use Jiminny\Repositories\Crm\LayoutRepository;
use Jiminny\Services\TeamService;
use Jiminny\VO\Repository\OnDemandActivitySearch\Criteria;
class ActivitySearch
{
private Container $container;
public function __construct(Container $container)
{
$this->container = $container;
}
public function getOnDemandPageFilters(): FilterDefinitionCollection
{
return FilterDefinitionCollection::make(
Collection::make([
// special case filters
FilterDefinition\ActivityStatusIn::class,
FilterDefinition\ActivityUpdatedDate::class,
FilterDefinition\ActivityRecordingStopped::class,
FilterDefinition\ActivityFilter::class,
FilterDefinition\ExternalId::class,
FilterDefinition\NudgeRunId::class,
FilterDefinition\ParticipantUserIn::class,
FilterDefinition\PartnerFilterDefinition::class,
// healthy restrictions
RestrictTeam::class,
RestrictUserGroupScope::class,
RestrictActivityChannel::class,
RestrictUserActive::class,
FilterDefinition\Security\PrivateMeetingsForCurrentUserOnly::class,
// regular filters
FilterDefinition\ActivityActualDate::class,
FilterDefinition\ActivityChannel::class,
FilterDefinition\ActivityDurationRange::class,
FilterDefinition\ActivityPlaylistIn::class,
FilterDefinition\ActivityProviderIn::class,
FilterDefinition\ActivityRecorded::class,
FilterDefinition\ActivityType::class,
FilterDefinition\CoachingFeedbackAverageScore::class,
AutoScoreFilter::class,
AiCallScoreFilter::class,
FilterDefinition\CoachingFeedbackCoachUserIn::class,
FilterDefinition\CrmFieldCollection::class,
FilterDefinition\CurrentStage::class,
FilterDefinition\Customer::class,
FilterDefinition\CustomerMonologueDuration::class,
FilterDefinition\CustomerQuestionCount::class,
FilterDefinition\DealAge::class,
DealCloseDate::class,
FilterDefinition\DealValue::class,
FilterDefinition\EngagingQuestionCount::class,
FilterDefinition\ShowInternalExternalActivitiesFilter::class,
FilterDefinition\HasTranscription::class,
FilterDefinition\InsightfulQuestionCount::class,
FilterDefinition\LanguageFilterDefinition::class,
FilterDefinition\LoggedToCrm::class,
FilterDefinition\OrganiserGroupIn:[PASSWORD]
FilterDefinition\OrganiserUserIn::class,
FilterDefinition\PatienceRange::class,
PlaybackTopicFilterDefinition::class,
FilterDefinition\ProviderFilterDefinition::class,
FilterDefinition\SortBy::class,
FilterDefinition\SpeechRate::class,
FilterDefinition\StageAtCallFilterDefinition::class,
FilterDefinition\TalkTimeRatio::class,
FilterDefinition\TeamMemberUserIn::class,
FilterDefinition\TranscriptionComposite::class,
FilterDefinition\UserMonologueDuration::class,
FilterDefinition\UserQuestionCount::class,
FilterDefinition\CommentCountRange::class,
FilterDefinition\HasPendingAiCrmNotes::class,
])
->map(fn (string $className): FilterDefinition => $this->container->make($className))
->all(),
);
}
public function getOnDemandPageFilterSet(Criteria $criteria, User $consumer): FilterDefinitionCollection
{
return $this
->getOnDemandPageFilters()
->withCriteria($criteria)
->withConsumer($consumer)
->withRestrictions($consumer->getTeam());
}
/**
* @return string[]
*/
public function getArrayFilterKeys(User $consumer): array
{
return $this
->getOnDemandPageFilters()
->withConsumer($consumer)
->getPropertyTypes([FilterDefinitionCollection::PROPERTY_TYPE_ARRAY])
->keys()
->filter(static fn (string $key): bool => ! str_contains($key, '.'))
->values()
->all();
}
private function getTeamInsightsPageFilters(bool $isExport = false): FilterDefinitionCollection
{
$dateRangeFilterClass = $isExport
? FilterDefinition\TeamInsights\ConversationExport\DateRangeFilter::class
: FilterDefinition\TeamInsights\DateRangeFilter::class;
return FilterDefinitionCollection::make(
Collection::make([
// special cases
$dateRangeFilterClass,
FilterDefinition\TeamInsights\Exists::class,
// healthy restrictions
RestrictTeam::class,
RestrictUserGroupScope::class,
RestrictActivityChannel::class,
RestrictPublicActivitiesOnly::class,
RestrictUserActive::class,
// regular filters
FilterDefinition\ActivityChannel::class,
FilterDefinition\TeamInsights\ActivityDurationRange::class,
FilterDefinition\ActivityPlaylistIn::class,
FilterDefinition\ActivityProviderIn::class,
FilterDefinition\TeamInsights\ActivityRecorded::class,
FilterDefinition\ActivityType::class,
FilterDefinition\CoachingFeedbackAverageScore::class,
AutoScoreFilter::class,
AiCallScoreFilter::class,
FilterDefinition\CoachingFeedbackCoachUserIn::class,
FilterDefinition\CrmFieldCollection::class,
FilterDefinition\Customer::class,
FilterDefinition\CurrentStage::class,
FilterDefinition\CustomerMonologueDuration::class,
FilterDefinition\CustomerQuestionCount::class,
FilterDefinition\DealAge::class,
DealCloseDate::class,
FilterDefinition\DealValue::class,
FilterDefinition\EngagingQuestionCount::class,
FilterDefinition\ShowInternalExternalActivitiesFilter::class,
FilterDefinition\InsightfulQuestionCount::class,
FilterDefinition\LanguageFilterDefinition::class,
FilterDefinition\LoggedToCrm::class,
FilterDefinition\TeamInsights\UserInFilter::class,
FilterDefinition\TeamInsights\UserGroupInFilter::class,
FilterDefinition\PatienceRange::class,
PlaybackTopicFilterDefinition::class,
FilterDefinition\ProviderFilterDefinition::class,
FilterDefinition\SortBy::class,
FilterDefinition\SpeechRate::class,
FilterDefinition\StageAtCallFilterDefinition::class,
FilterDefinition\TalkTimeRatio::class,
FilterDefinition\TeamMemberUserIn::class,
FilterDefinition\TranscriptionComposite::class,
FilterDefinition\UserMonologueDuration::class,
FilterDefinition\UserQuestionCount::class,
FilterDefinition\CommentCountRange::class,
// Relevant for topics in deals.
ClosedDealsFilter::class,
HasTopicTriggersFilterDefinition::class,
TopicFilterDefinition::class,
])
->map(fn (string $className): FilterDefinition => $this->container->make($className))
->all(),
);
}
private function getDealInsightsPageFilters(
bool $useCreatedDate = false,
bool $includeDealType = false,
bool $includePipeline = false,
): FilterDefinitionCollection {
if ($useCreatedDate) {
$periodFilterClass = FilterDefinition\DealInsights\CreatedPeriodFilter::class;
} else {
$periodFilterClass = FilterDefinition\DealInsights\ClosingPeriodFilter::class;
}
$filterSet = [
RestrictTeam::class,
$periodFilterClass,
FilterDefinition\DealInsights\UserInFilter::class,
FilterDefinition\DealInsights\UserGroupInFilter::class,
FilterDefinition\DealInsights\DealStageInFilter::class,
FilterDefinition\DealInsights\DealNameFilter::class,
];
if ($includePipeline) {
$filterSet[] = FilterDefinition\DealInsights\DealPipelineInFilter::class;
}
if ($includeDealType) {
$filterSet[] = FilterDefinition\DealInsights\DealTypeInFilter::class;
}
return FilterDefinitionCollection::make(
Collection::make($filterSet)
->map(fn (string $className): FilterDefinition => $this->container->make($className))
->all(),
);
}
public function getTeamInsightsPageFilterSet(
Criteria $criteria,
User $consumer,
bool $isExport = false
): FilterDefinitionCollection {
return $this
->getTeamInsightsPageFilters($isExport)
->withCriteria($criteria)
->withConsumer($consumer)
->withRestrictions($consumer->getTeam());
}
public function getDealInsightsPageFilterSet(
Criteria $criteria,
User $consumer
): FilterDefinitionCollection {
$includeDealType = $this->shouldIncludeDealType($consumer);
$includePipeline = $this->shouldIncludePipeline($consumer);
$useCreatedDate = $this->shouldUseCreatedDate($consumer);
return $this
->getDealInsightsPageFilters($useCreatedDate, $includeDealType, $includePipeline)
->withCriteria($criteria)
->withConsumer($consumer);
}
public function getTeamAiAutomationFilterSet(
Criteria $criteria,
User $consumer
): FilterDefinitionCollection {
return $this
->getTeamAiAutomationPageFilterSet()
->withCriteria($criteria)
->withConsumer($consumer);
}
private function getTeamAiAutomationPageFilterSet(): FilterDefinitionCollection
{
$filterSet = [
RestrictTeam::class,
FilterDefinition\DealInsights\DealStageInFilter::class,
];
return FilterDefinitionCollection::make(
Collection::make($filterSet)
->map(fn (string $className): FilterDefinition => $this->container->make($className))
->all(),
);
}
public function getHomepageFilterSet(Criteria $criteria, User $consumer): FilterDefinitionCollection
{
$filterDefinitionCollection = FilterDefinitionCollection::make(
Collection::make([
RestrictTeam::class,
RestrictUserGroupScope::class,
RestrictActivityChannel::class,
RestrictUserActive::class,
FilterDefinition\Security\PrivateMeetingsForCurrentUserOnly::class,
FilterDefinition\ActivityActualDate::class,
FilterDefinition\Customer::class,
FilterDefinition\ActivityChannel::class,
FilterDefinition\ActivityDurationRange::class,
FilterDefinition\ActivityProviderIn::class,
FilterDefinition\ActivityRecorded::class,
FilterDefinition\ActivityRecordingStopped::class,
FilterDefinition\ActivityScheduledDate::class,
FilterDefinition\ActivityStatusIn::class,
FilterDefinition\LoggedToCrm::class,
FilterDefinition\OrganiserUserIn::class,
FilterDefinition\OrganiserUserNotIn::class,
FilterDefinition\ProviderFilterDefinition::class,
FilterDefinition\SortBy::class,
FilterDefinition\UserGroupInOptionalFilter::class,
FilterDefinition\OnlyActiveUsers::class,
])
->map(fn (string $className): FilterDefinition => $this->container->make($className))
->all(),
);
$filterDefinitionCollection->withCriteria($criteria);
$filterDefinitionCollection->withConsumer($consumer);
return $filterDefinitionCollection;
}
public function getPartnerFilterSet(Criteria $criteria): FilterDefinitionCollection
{
$filterDefinitionCollection = FilterDefinitionCollection::make(
Collection::make([
RestrictActivityChannel::class,
FilterDefinition\OrganiserTeamIn::class,
FilterDefinition\ActivityUpdatedDate::class,
FilterDefinition\ActivityStatusIn::class,
FilterDefinition\SortBy::class,
])
->map(fn (string $className): FilterDefinition => $this->container->make($className))
->all()
);
$filterDefinitionCollection->withCriteria($criteria);
return $filterDefinitionCollection;
}
private function shouldIncludeDealType(User $user): bool
{
$crmConfig = $user->getTeam()->getCrmConfiguration();
$crmProviderName = $crmConfig->getProviderName();
if (! array_key_exists($crmProviderName, Field::BUSINESS_TYPE_FIELDS)) {
return false;
}
$layoutRepository = app(LayoutRepository::class);
$layoutFields = $layoutRepository->getDealInsightLayoutFields($crmConfig);
$dealTypeField = Field::BUSINESS_TYPE_FIELDS[$crmProviderName];
if (! in_array($dealTypeField, $layoutFields)) {
return false;
}
return true;
}
private function shouldIncludePipeline(User $user): bool
{
$crmConfig = $user->getTeam()->getCrmConfiguration();
$crmProviderName = $crmConfig->getProviderName();
if (in_array($crmProviderName, [
Configuration::PROVIDER_SALESFORCE,
Configuration::PROVIDER_INTEGRATION_APP,
])) {
return false;
}
return true;
}
private function shouldUseCreatedDate(User $user): bool
{
$teamService = app(TeamService::class);
return ! $teamService->useDealInsightsClosedDateFilter($user->getTeam());
}
}
Sync Changes
Hide This Notification
Code changed:
Hide
15
4
Previous Highlighted Error
Next Highlighted Error
<?php
declare(strict_types=1);
namespace Jiminny\Repositories;
use Carbon\CarbonImmutable;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Support\Carbon;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Pagination\LengthAwarePaginator;
use Illuminate\Support\Facades\DB;
use Jiminny\Models\AutomatedReport;
use Jiminny\Models\AutomatedReportResult;
use Jiminny\Models\Team;
use Jiminny\Models\User;
use Jiminny\Services\Kiosk\AutomatedReports\AutomatedReportsService;
use Jiminny\Services\Kiosk\AutomatedReports\ReportSort;
use Jiminny\Services\Kiosk\AutomatedReports\ReportSortDirection;
class AutomatedReportsRepository
{
/**
* Create a new automated report
*
* @param array $data
*
* @return AutomatedReport
*/
public function create(array $data): AutomatedReport
{
return AutomatedReport::create($data);
}
/**
* Find an automated report by UUID
*
* @param string $uuid
*
* @return AutomatedReport|null
*/
public function findByUuid(string $uuid): ?AutomatedReport
{
return AutomatedReport::where('uuid', AutomatedReport::toOptimized($uuid))->first();
}
public function findByIdOrUuid(string $idOrUuid): ?AutomatedReport
{
if (is_numeric($idOrUuid)) {
return AutomatedReport::find((int) $idOrUuid);
}
return AutomatedReport::where('uuid', AutomatedReport::toOptimized($idOrUuid))->first();
}
/**
* Retrieve all standard (non-Ask Jiminny) automated reports.
*
* @param string $sortColumn The column to sort by. Allowed values: 'created_by', 'created_at'. Defaults to 'created_at'.
* @param string $sortDirection The sort direction. Allowed values: 'asc', 'desc'. Defaults to 'desc'.
*
* @return Collection<AutomatedReport>
*/
public function getAllStandardReports(
string $sortColumn = 'created_at',
string $sortDirection = 'desc'
): Collection {
return $this->buildSortedQuery($sortColumn, $sortDirection)
->whereNot('type', AutomatedReportsService::TYPE_ASK_JIMINNY)
->get();
}
/**
* Retrieve all Ask Jiminny reports created by the given user.
*
* @param User $user The user whose reports to retrieve.
* @param string $sortColumn The column to sort by. Allowed values: 'created_by', 'created_at'. Defaults to 'created_at'.
* @param string $sortDirection The sort direction. Allowed values: 'asc', 'desc'. Defaults to 'desc'.
*
* @return Collection<AutomatedReport>
*/
public function getAskJiminnyReportsByUser(
User $user,
string $sortColumn = 'created_at',
string $sortDirection = 'desc'
): Collection {
return $this->buildSortedQuery($sortColumn, $sortDirection)
->where('type', AutomatedReportsService::TYPE_ASK_JIMINNY)
->where('created_by', $user->getId())
->get();
}
private function buildSortedQuery(string $sortColumn, string $sortDirection): \Illuminate\Database\Eloquent\Builder
{
$allowedColumns = ['created_by', 'created_at'];
if (! in_array($sortColumn, $allowedColumns)) {
$sortColumn = 'created_at';
}
$sortDirection = strtolower($sortDirection) === 'asc' ? 'asc' : 'desc';
$query = AutomatedReport::query()->with(['creator', 'team']);
if ($sortColumn === 'created_by') {
$query->leftJoin('users', 'users.id', '=', 'automated_reports.created_by')
->orderByRaw("users.name COLLATE utf8mb4_unicode_ci {$sortDirection}")
->select('automated_reports.*');
} else {
$query->orderBy($sortColumn, $sortDirection);
}
return $query;
}
/**
* Get all active and enabled reports with active teams for the specified frequency.
*
* @param string $frequency
*
* @return Collection<AutomatedReport>
*/
public function getActiveReportsByFrequency(string $frequency): Collection
{
return AutomatedReport::where('automated_reports.status', true)
->where('automated_reports.frequency', $frequency)
->join('teams', 'automated_reports.team_id', '=', 'teams.id')
->where('teams.status', Team::STATUS_ACTIVE)
->where(function ($query) {
$query->whereNull('automated_reports.expires_at')
->orWhere('automated_reports.expires_at', '>=', now()->toDateString());
})
->select('automated_reports.*')
->get();
}
/**
* Update an automated report
*
* @param AutomatedReport $report
* @param array $data
*
* @return AutomatedReport
*/
public function update(AutomatedReport $report, array $data): AutomatedReport
{
$report->update($data);
return $report;
}
/**
* Create a new automated report result.
*
* @param array $data The data to create the automated report result with.
*
* @return AutomatedReportResult The newly created automated report result.
*/
public function createResult(array $data): AutomatedReportResult
{
return AutomatedReportResult::create($data);
}
/**
* Find an automated report result by UUID.
*
* @param string $uuid The UUID to find the automated report result with.
*
* @return AutomatedReportResult|null The automated report result if found, otherwise null.
*/
public function findResultByUuid(string $uuid): ?AutomatedReportResult
{
return AutomatedReportResult::where('uuid', AutomatedReportResult::toOptimized($uuid))->first();
}
public function findResultByUuidForUser(string $uuid, User $user): ?AutomatedReportResult
{
return AutomatedReportResult::query()
->where('uuid', AutomatedReportResult::toOptimized($uuid))
->whereHas('report', static function ($query) use ($user): void {
$query->where('team_id', $user->getTeamId())
->where('created_by', $user->getId());
})
->first();
}
public function findChildResult(AutomatedReportResult $result, string $type): ?AutomatedReportResult
{
return AutomatedReportResult::query()
->where('parent_id', $result->getId())
->where('media_type', $type)
->first();
}
public function getGeneratedNotSentResults(): Collection
{
return AutomatedReportResult::query()
->whereNotNull('generated_at')
->whereNull('sent_at')
->where('status', AutomatedReportResult::STATUS_GENERATED)
->whereHas('report')
->with('report')
->get();
}
public function getPaginatedUserReports(
User $user,
ReportSort $sort,
ReportSortDirection $sortDirection,
int $resultsPerPage,
int $page,
?Carbon $fromDate,
?Carbon $toDate,
array $teamIds,
array $reportTypes,
?string $name,
): LengthAwarePaginator {
$query = AutomatedReportResult::query()
->whereNotNull('automated_report_results.generated_at')
->join('automated_reports', 'automated_report_results.report_id', '=', 'automated_reports.id')
->where('automated_reports.team_id', $user->getTeamId())
->whereJsonContains('automated_reports.recipients->users', $user->getId())
->orderByRaw("$sort->value COLLATE utf8mb4_unicode_ci {$sortDirection->value}")
->select('automated_report_results.*')
->with('report.team');
if ($fromDate !== null && $toDate !== null) {
$query->whereBetween('generated_at', [$fromDate, $toDate]);
}
if (! empty($teamIds)) {
$query->where(function ($q) use ($teamIds) {
foreach ($teamIds as $id) {
$q->orWhereJsonContains('automated_reports.groups', $id);
}
});
}
if (! empty($reportTypes)) {
$query->whereIn('automated_reports.type', $reportTypes);
}
if (! empty($name)) {
$query->whereLike('name', "%$name%");
}
return $query->paginate($resultsPerPage, ['*'], 'page', $page);
}
public function countUserReports(User $user): int
{
return AutomatedReportResult::query()
->whereNotNull('generated_at')
->whereNotNull('sent_at')
->whereHas('report', function ($q) use ($user) {
$q->where('team_id', $user->getTeamId())
->whereJsonContains('recipients->users', $user->getId());
})
->count();
}
/**
* Get report IDs for a specific team
*
* @param Team $team
*
* @return \Illuminate\Support\Collection
*/
public function getReportIdsByTeam(Team $team): \Illuminate\Support\Collection
{
return AutomatedReport::where('team_id', $team->getId())->pluck('id');
}
/**
* Get all reports for a specific team
*
* @param Team $team
*
* @return Collection
*/
public function getReportsByTeam(Team $team): Collection
{
return AutomatedReport::where('team_id', $team->getId())->get();
}
/**
* Get all report results for a specific report
*
* @param AutomatedReport $report
*
* @return Collection
*/
public function getResultsByReport(AutomatedReport $report): Collection
{
return $this->getResultsByReportQuery($report)->get();
}
public function getResultsByReportQuery(AutomatedReport $report): Builder
{
return AutomatedReportResult::where('report_id', $report->getId());
}
public function getReportResultsQueryForRetention(Team $team, CarbonImmutable $retentionDate): Builder
{
$reportIds = $this->getReportIdsByTeam($team);
return AutomatedReportResult::query()->whereIn('report_id', $reportIds)
->whereRaw('IFNULL(generated_at, created_at) <= ?', [$retentionDate]);
}
/**
* @param int|null $teamId Optional team ID to filter results
*
* @return \Illuminate\Support\Collection<int, int> Collection of team IDs
*/
public function getTeamIdsWithReportsResults(?int $teamId = null): \Illuminate\Support\Collection
{
$query = DB::table('automated_reports')
->join('teams', 'automated_reports.team_id', '=', 'teams.id')
->select('teams.id')
->distinct();
if ($teamId !== null) {
$query->where('teams.id', $teamId);
}
return $query->pluck('teams.id');
}
}
Project
Project
New File or Directory…
Expand Selected
Collapse All
Options
Hide...
|
PhpStorm
|
faVsco.js – ActivitySearch.php
|
NULL
|
11059
|
|
11058
|
+SlackEDHomeDMSActivityFilesLater..•More+FileEditV +SlackEDHomeDMSActivityFilesLater..•More+FileEditViewGoHistoryWindowHelpJiminny ...# Starredplatform-inner-teamChannels# ai-chapter# alerts# backend# confusion-clinic# curiosity_lab# engineering# frontend# general# infra-changes# jiminny-bg# platform-tickets# product launches# random# releases# sofia-office# support# thank-yous# the_people_of jimi…..Direct messagesAneliya Angelova, ...Steliyan GeorgievAdelina Petrova, Ili.... Adelina PetrovaO. Calea Dimitravo→Search Jiminny IncAneliya Angelova, Nikolay Yankov, Steliyan GeorgievMessagesAdd canvas+Nikolay Yankov 10:45 AMпиши кат оя рьннешLukas Kovalik 10:52 AMзабавих се че ми се разбазикаха settings за средипуснах и мина и fail-наима result но e failedзначиREASON_NOT_ENOUGH_ACTIVITIESвиж дали има нещо в OD със този филтьрNikolay Yankov 11:01 AMДобреNikolay Yankov 11:39 AMя рьнни пак LukasLukas Kovalik 11:43 AMготовосьщотоCompetitive pitches беше втория нали такаNikolay Yankov 12:04 PMДа, там има 14 активитита, защо не сработи този пьт?Lukas Kovalik 12:05 PMпак изглежда sequenceгледам гоMessage Aneliya Angelova, Nikolay Yankov, Steliyan Georgiev+Aa> 0ladl= Support Daily • in 2h 50 m100% <47Tue 14 Apr 12:10:2086 0Today ~...
|
NULL
|
NULL
|
NULL
|
11058
|
|
11057
|
PhpStormFileEditViewNavigateCodeLaravelRefactorFV PhpStormFileEditViewNavigateCodeLaravelRefactorFV faVsco.s v#11894 on JY-18909-automated-reports-ask-liminny k vProject vToolsWindowHelpD AutomatedReports© ActivityTypeService.© AskJiminnyReportAc© AutomatedReportsCi© AutomatedReportsSt© DealStagesService.p© RecipientsService.ph® ReportSort.php(e) Reporisonbirection.Kloskservice.php> M Mail• MeetingGeneratorNotificationDJ OAuth2D RecallAlD SecurityC StrategyStreamingD TeamTelephonyUserPilotM Webhook© AbstractService.php© ActivityProviderFactory.ph|© ActivityService.php© ApiResponseService.php© ConferenceService.php© InsightSeatService.php© InstantMeetingService.php© IntercomService.php©IpapiClient.php©IpapiService.php© ParticipantShareService.ph© PlanhatService.php© PlaybackService.phpPlaybackVideoOnlyService©PlaybookCategoryService./© PlaylistGeneratorInterface.© ResolveTeamCrmConnecti© SimpleThrottleService.php© SlackService.php© SocialAccountService.php© SoftPhoneService.phpC) TeamDeactivatedService.p© TeamOwnerService.php©TeamService.php© TranscodeParameterResol© UserService.php© Uuid.php› D Traits› D UseCases> D UserDUtils• I validationvIVO~ D Repositoryv @ OnDemandActivitySearc© Criteria.php© TranscriptionKeywordP:Tests passed: 1 (a minute ago)© ReportController.php© AutomatedReportsCommand.phpJiminnybeouecommana.ong= custom.log< console EUi= laravel.logA SF [jiminny@localhost]A HS_local [jiminny@localhost]A console [PROD]console SlAGiNG© AskJiminnyReportActivityService.php© ActivitySearch.php xAskJiminnyReportActivityServiceTest.php© RequestGenerateAskJiminnyReportJobTest.php© AutomatedReportsSendCommand.php© AddLayoutEntities.php© Team.php© AutomatedReportsRepository.php X© AutomatedReportsService.phpC CreateHeldActivityEvent.php© Criteria.php<?phpdeclare(strict_types=1);(e TrackProvidernstallled-vent.ononamespace Jiminny\Component\ActivitySearch\Service;© CreateActivityLoggedEvent.php© UserPilotActivityListener.php(©) ActivityLogged.php(C) AutomatedReportsCallbackService.php© RequestGenerateAskJiminnyReportJob.phpRequestGenerateReportJob.php© AutomatedReportResult.php(C) AutomatedReport.phpuseclass ActivitySearchclass Automacedкeрortskepo o:815 X4 л83114115116117118119120121123/*** Retrieve all standard (non-Ask Jiminny) M107* @param string $sortColumnThe column tc* Cparam string ssortDirection The sort dir 109* @return Collection<AutomatedReport>11111212 usagespublic function getAllStandardReports(string $sortColumn = 'created_at',string $sortDirection = 'desc'): Collection {...}113114115116 F1171/*** Retrieve all Ask Liminay reports created {119* Oodrdll usernusenIne user Ynos* @param string $sortColumnIne corumn cc* Oparam string $sortDirection The sort dire197* @return Collection<AutomatedReport>198*/—19914 usages200public function getAskJiminnyReportsByUser(User $user,string $sortColumn = 'created_at',surno ssortutreccion = 'desc'): Collection {...J2074254233234—2352 usages236private function buildSortedQuery(string $sor]237— 244/**245* Get all active and enabled reports with ac247* @param string $frequency148* dreturh coLcectzon<aucomaredкeport.L0723 usages260public function getActiveReportsByFrequency(s)7 usagesprivate Container $container;public function __construct(Container $container){.}public function getOnDemandPageFilters(): FilterDefinitionCollectionf...}public function get0nDemandPageFilterSet(Criteria $criteria, User $consumer): FilterDefinitreturn $this->getOnDemandPageFilters()-›withCriteria($criteria)-›withConsumer ($consumer)->withRestrictions($consumer->getTeam()):/*** pretuea str ingt)9 usagespublic function getArrayFilterKeys(User $consumer): array{...;1 usageprivate function getTeamInsightsPageFilters(bool $isExport = false): FilterDefinitionCollec1 usageprivate function getDealInsightsPageFilters(bool $useCreatedDate = false,booL pincLudebeallype = ralse.bool +inctuderipellhe - Talse): FilterDefinitionCollection {..}public function getTeamInsightsPageFilterSet(Criteria $criteria,User $consumer,bool $isExport = false): FilterDefinitionCollection i...rpublic function getDealInsightsPageFilterSet(Criteria $criteria,user consunen): FilterDefinitionCollectionf...}1 usagepublic function getTeamAiAutomationFilterSet(Criteria $criteria,User $consumerSupport Daily • in 2 h 50 mAAskJiminnyReportActivityServiceT…Defaults100% C•Tue 14 Apr 12:10:20CascadeFixing ReportControllerAutomated Report MarFixing Ask Jiminny Rep+D..Now let's run the test to verifvwtests/Unxt/Servsces/Kiosk/Automate/meports/AskJ1minnyreportActivätyserviceTest-php --no-coveragecould not open input Tile: /var/www/ncml/artisanCommand dockeldoster nxe ceockes /kJosk/AuP /ape/a/poras/A5kJ1minyReportActivityServiceTest.php --no-coverageCould not open input file: /app/artisanCommand dockeroocker exec oocker vand ioash -c"cd /var/www&& php artisan testLests unlu services Klosk Aucomaceakeporcs AskJiminnykeportAccivityservicelest.ono =-no-coverade D&l'Could not open input file: artisanCommand docken• docker exec docker_lamp_1 bash -c "find / -name artisan -maxdepth 6 2>/dev/null | head -5"/home/jiminny/artisan"cd /homeiminny && php artisan test•dests/unxe/servkces/K1osk/AusomatedReports/AskJ1maynyReportActiVatyServiceTest.php --no-coverage 2>&1"PASSgetTests\Unit\Services\Kiosk\AutomatedReports\AskJiminnyReportActivityServiceTesta fittersemoty when no resultsE tatt tnt hperiod date filters•der aculvicvids bassess snazer fsequence number to disable first _ 0.025All 8 tests pass. Here's a summary:Root Cause & FixRoot cause: buildRequestParamsFromSearch never set sequence number in the request params, so Criteria::createFromRequest defaulted it to 0Since isFirstRequest() returns true when sequenceNumber === 0, several implicit defaults were silently applied:ctivitvourationRande → min duration = 1 Ttlters ouf o-second acrivitiesi• ActivityRecorded → only_recorded = 1 (restricts to recorded activities only)OrganiserGroupIn → applies user's default group as a filtelThe frontend URL you noticed uses sequence_number=4, which disables these defaults - explaining why the frontend returned activities but the serviceretumee uFix: AskJiminnyReportActivityService.php:51—added 'sequence_number' » 1 to the Criteria::createFromRequest merge, ensuring isFirstRequest() returns false and no implicit defaults are injected.lest added: testbetacc1cylasPassesNonzerosequencenumberloDisablerarsckequestberaulus assers that the captured uriteria ob ect nas 1srirstRequest () === false.Öul ..Vew allliItlle win changesvapp/Services/Kiosk/AutomatedReports/D AskJiminnyReportActivityService.php +1 -1Reject allAccept allAsk anything (2*L)+ <> Code Claude Sonnet 4.6Winasun leamsTO/'2uir-o( 4 spaces...
|
NULL
|
NULL
|
NULL
|
11057
|
|
11056
|
+SlackEDHomeDMSActivityFilesLater..•More+FileEditV +SlackEDHomeDMSActivityFilesLater..•More+FileEditViewGoHistoryWindowHelpJiminny ...# Starredplatform-inner-teamChannels# ai-chapter# alerts# backend# confusion-clinic# curiosity_lab# engineering# frontend# general# infra-changes# jiminny-bg# platform-tickets# product launches# random# releases# sofia-office# support# thank-yous# the_people_of jimi…..Direct messagesAneliya Angelova, ...Steliyan GeorgievAdelina Petrova, Ili.... Adelina PetrovaO. Calea Dimitravo→Search Jiminny IncAneliya Angelova, Nikolay Yankov, Steliyan GeorgievMessagesAdd canvas+Nikolay Yankov 10:45 AMпиши кат оя рьннешLukas Kovalik 10:52 AMзабавих се че ми се разбазикаха settings за средипуснах и мина и fail-наима result но e failedзначиREASON_NOT_ENOUGH_ACTIVITIESвиж дали има нещо в OD със този филтьрNikolay Yankov 11:01 AMДобреNikolay Yankov 11:39 AMя рьнни пак LukasLukas Kovalik 11:43 AMготовосьщотоCompetitive pitches беше втория нали такаNikolay Yankov 12:04 PMДа, там има 14 активитита, защо не сработи този пьт?Lukas Kovalik 12:05 PMпак изглежда sequenceгледам гоMessage Aneliya Angelova, Nikolay Yankov, Steliyan Georgiev+Aa> 0ladl= Support Daily • in 2h 50 m100% <47Tue 14 Apr 12:10:1886 0Today ~...
|
NULL
|
NULL
|
NULL
|
11056
|