Possibility to recalculate the formulas by formula?

Collapse
X
 
  • Time
  • Show
Clear All
new posts

  • shalmaxb
    replied
    Hi, meanwhile this became an extension, which the member telecastg developed. You may find it here: https://payhip.com/b/28Dhw
    It had been adapted to work with 7.x and is easy to install and to configure. It is really worth its money.
    Last edited by shalmaxb; 04-15-2022, 11:32 AM.

    Leave a comment:


  • DashingUno
    replied
    Hi, telecastg is your solution still valid for current (7.0.10) version of Espo?

    I'm getting a 500 error:
    Code:
     "message": "Slim Application Error"
    And this is the Espo log:

    Code:
    [2022-04-15 10:09:36] ERROR: Slim Application Error Type: Error Code: 0 Message: Call to undefined method Espo\Custom\Controllers\RecalculateFormula::getMassActionParamsFromData() File: /var/www/html/custom/Espo/Custom/Controllers/RecalculateFormula.php Line: 12 Trace: #0 /var/www/html/application/Espo/Core/Api/ActionProcessor.php(120): Espo\Custom\Controllers\RecalculateFormula->postActionUnrestrictedRecalculateFormula(Array, Object(stdClass), Object(Espo\Core\Api\RequestWrapper), Object(Espo\Core\Api\ResponseWrapper)) #1 /var/www/html/application/Espo/Core/Api/RequestProcessor.php(136): Espo\Core\Api\ActionProcessor->process('RecalculateForm...', 'unrestrictedRec...', Object(Espo\Core\Api\RequestWrapper), Object(Espo\Core\Api\ResponseWrapper)) #2 /var/www/html/application/Espo/Core/Api/RequestProcessor.php(111): Espo\Core\Api\RequestProcessor->proceed(Object(Espo\Core\Api\RequestWrapper), Object(Espo\Core\Api\ResponseWrapper)) #3 /var/www/html/application/Espo/Core/Api/RequestProcessor.php(82): Espo\Core\Api\RequestProcessor->processInternal(Object(Espo\Core\Api\Route), Object(Espo\Core\Api\RequestWrapper), Object(Espo\Core\Api\ResponseWrapper)) #4 /var/www/html/application/Espo/Core/Api/Starter.php(103): Espo\Core\Api\RequestProcessor->process(Object(Espo\Core\Api\Route), Object(Espo\Core\Api\RequestWrapper), Object(Espo\Core\Api\ResponseWrapper)) #5 /var/www/html/vendor/slim/slim/Slim/Handlers/Strategies/RequestResponse.php(43): Espo\Core\Api\Starter->Espo\Core\Api\{closure}(Object(Slim\Psr7\Request), Object(Slim\Psr7\Response), Array) #6 /var/www/html/vendor/slim/slim/Slim/Routing/Route.php(384): Slim\Handlers\Strategies\RequestResponse->__invoke(Object(Closure), Object(Slim\Psr7\Request), Object(Slim\Psr7\Response), Array) #7 /var/www/html/vendor/slim/slim/Slim/MiddlewareDispatcher.php(81): Slim\Routing\Route->handle(Object(Slim\Psr7\Request)) #8 /var/www/html/vendor/slim/slim/Slim/MiddlewareDispatcher.php(81): Slim\MiddlewareDispatcher->handle(Object(Slim\Psr7\Request)) #9 /var/www/html/vendor/slim/slim/Slim/Routing/Route.php(341): Slim\MiddlewareDispatcher->handle(Object(Slim\Psr7\Request)) #10 /var/www/html/vendor/slim/slim/Slim/Routing/RouteRunner.php(84): Slim\Routing\Route->run(Object(Slim\Psr7\Request)) #11 /var/www/html/vendor/slim/slim/Slim/Middleware/RoutingMiddleware.php(59): Slim\Routing\RouteRunner->handle(Object(Slim\Psr7\Request)) #12 /var/www/html/vendor/slim/slim/Slim/MiddlewareDispatcher.php(147): Slim\Middleware\RoutingMiddleware->process(Object(Slim\Psr7\Request), Object(Slim\Routing\RouteRunner)) #13 /var/www/html/vendor/slim/slim/Slim/Middleware/ErrorMiddleware.php(107): class@anonymous->handle(Object(Slim\Psr7\Request)) #14 /var/www/html/vendor/slim/slim/Slim/MiddlewareDispatcher.php(147): Slim\Middleware\ErrorMiddleware->process(Object(Slim\Psr7\Request), Object(class@anonymous)) #15 /var/www/html/vendor/slim/slim/Slim/MiddlewareDispatcher.php(81): class@anonymous->handle(Object(Slim\Psr7\Request)) #16 /var/www/html/vendor/slim/slim/Slim/App.php(215): Slim\MiddlewareDispatcher->handle(Object(Slim\Psr7\Request)) #17 /var/www/html/vendor/slim/slim/Slim/App.php(199): Slim\App->handle(Object(Slim\Psr7\Request)) #18 /var/www/html/application/Espo/Core/Api/Starter.php(79): Slim\App->run() #19 /var/www/html/application/Espo/Core/ApplicationRunners/Api.php(49): Espo\Core\Api\Starter->start() #20 /var/www/html/application/Espo/Core/Application/RunnerRunner.php(85): Espo\Core\ApplicationRunners\Api->run() #21 /var/www/html/application/Espo/Core/Application.php(78): Espo\Core\Application\RunnerRunner->run('Espo\\Core\\Appli...', NULL) #22 /var/www/html/public/api/v1/index.php(37): Espo\Core\Application->run('Espo\\Core\\Appli...') #23 {main} Tips: To display error details in HTTP response set "displayErrorDetails" to true in the ErrorHandler constructor. [] []
    Last edited by DashingUno; 04-15-2022, 10:10 AM.

    Leave a comment:


  • telecastg
    commented on 's reply
    Excellent idea item , I posted a tutorial using this code as example. https://forum.espocrm.com/forum/deve...able-extension

  • telecastg
    commented on 's reply
    No you don't need that custom handler anymore, it was substituted by client/custom/src/unrestricted-recalculate-formula-handler.js

  • shalmaxb
    commented on 's reply
    telecastg, I had this code in client/custom/src/ before: https://forum.espocrm.com/forum/gene...4301#post64301.
    This was necessary for every entity, where I wanted the recalculate button. I think, these files are not longer necessary, because your unrestricted.... code provides the function for all entities.

  • telecastg
    commented on 's reply
    You're welcome shalmaxb what do you mean by "handlers" ? could you provide an example please ?

  • shalmaxb
    replied
    telecastg , I implemented and it works as expected, very elegant. Thank you a lot.
    By the way, from the former solution I have handler-files for every entity, where I used the button before in restricted form. These handlers are obsolete now, right?
    Last edited by shalmaxb; 02-21-2021, 11:12 PM.

    Leave a comment:


  • shalmaxb
    commented on 's reply
    In case of that lot of records this is to be actually considered. Will keep this in mind, when I ever come to many records (until now I have to handle only about 200)

  • item
    replied
    Hello,

    i don't know if "jobs" are too for admin acl, but another solution can be done by jobs.
    custom action, create a jobs who foreach... ->saveEntity(...)
    i work with many "jobs" solution because we have X million record .. when i try to recalculate some entity.. it's timeOut

    Regards

    Leave a comment:


  • item
    commented on 's reply
    many thanks

    maybe .. it's just my 2 cents.. because we talk about extension.. this can be one sample for learning how make extension ?

    Regards
    Last edited by item; 02-21-2021, 09:48 PM.

  • telecastg
    replied
    Originally posted by shalmaxb
    telecastg , wow, what a lot of work you put into it, I really appreciate. I will see, if I can try it tomorrow, here its late already. I will let you know, if it worked with me.
    No problem, let me know how it works please

    Enjoy your evening !
    Last edited by telecastg; 02-20-2021, 10:04 PM.

    Leave a comment:


  • shalmaxb
    replied
    telecastg , wow, what a lot of work you put into it, I really appreciate. I will see, if I can try it tomorrow, here its late already. I will let you know, if it worked with me.

    Leave a comment:


  • telecastg
    replied
    Hi shalmaxb ,

    I checked and the issue is originated in the back-end controller which throws a 403 error if the user is not admin. https://github.com/espocrm/espocrm/b...ecord.php#L507
    and in the back-end service class that also prevents the execution of the formula recalculation if the user is not admin.
    https://github.com/espocrm/espocrm/b...cord.php#L1864

    The solution if you only want to have this capability (formula recalculation by non admin users) for one entity, would be to override the function "postActionMassRecalculateFormula" in your custom entity's Controller class and the function "massRecalculateFormula" in your entity's custom Service class.

    However, thinking that you might want to apply this capability to several entities and not wanting to override each back-end controller and service class for each entity I propose this solution:

    Step 1
    Based on Maximus excellent button handler tutorial, create a custom button handler that will make an Ajax call to a custom back-end Controller.
    client/custom/src/unrestricted-recalculate-formula-handler,js
    Code:
    define('custom:unrestricted-recalculate-formula-handler', ['action-handler'], function (Dep) {
    
        return Dep.extend({
    
            actionRecalculate: function (data, e) {
    
                var data = this.getActionSelectionPostData();
                data['scope'] = this.view.scope;
                // make an Ajax call to a custom back-end controller class
                Espo.Ajax.postRequest('RecalculateFormula', data).then(function (result) {
                    // refresh the view after the back-end operation has been successfuly completed
                    this.view.model.fetch();
                    this.view.notify('Saved', 'success');
                    this.view.reRender();
                }.bind(this));
            },
    
            initRecalculate: function () {
            },
    
            controlButtonVisibility: function () {
            },
    
            getActionSelectionPostData: function () {
                var data = {};
                var ids = false;
                if (this.view.model.id) {
                    data.ids = [];
                    data.ids.push(this.view.model.id);
                }
                return data;
            }
        });
    });
    Step 2
    Create a custom router entry that will tell Espo what back-end controller and what function to call, when the Ajax call is made to a url "RecalculateFormula"
    custom/Espo/Custom/Resources/routes.json
    Code:
    [
        {
            "route": "/RecalculateFormula",
            "method": "post",
            "params": {
                "controller": "RecalculateFormula",
                "action": "unrestrictedRecalculateFormula"
            }
        }
    ]
    Step 3
    Create the custom back-end controller "RecalculateFormula" invoked by the custom route
    custom/Espo/Custom/Controllers/RecalculateFormula.php
    PHP Code:
    <?php
    namespace Espo\Custom\Controllers;

    class 
    RecalculateFormula extends \Espo\Core\Templates\Controllers\Base
    {
        public function 
    postActionUnrestrictedRecalculateFormula($params$data$request)
        {
            
    // make sure that the user has "edit" privileges over the entity
            
    if (!$this->getAcl()->check($data->scope'edit')) throw new Forbidden();

            
    // invoke the service class that will actually implement the business logic
            
    return $this->getServiceFactory()->create('RecalculateFormula')->unrestrictedRecalculateFormula($this->getMassActionParamsFromData($data),$data->scope);
        }
    }

    Step 4
    Create the custom back-end service class invoked by the custom back-end controller
    custom/Espo/Custom/Services/RecalculateFormula.php
    PHP Code:
    <?php
    namespace Espo\Custom\Services;

    class 
    RecalculateFormula extends \Espo\Core\Templates\Services\Base
    {
        public function 
    unrestrictedRecalculateFormula(array $paramsstring $scope)
        {
            
    $count 0;
            
    $selectParams $this->convertMassActionSelectParams($params);
            
    $selectParams["from"] = $scope;
            
    $collection $this->getEntityManager()->getRepository($scope)->sth()->find($selectParams);

            foreach (
    $collection as $entity) {
                
    $this->getEntityManager()->saveEntity($entity);
                
    $count++;
            }

            return [
                
    'count' => $count,
            ];
        }
    }

    Step 5
    Go to your custom entity clientDefs metadata file and insert this code. (substitute "{your-entity-name}" for your actual entity name eg: "Lead").
    custom/Espo/Custom/Resources/metadata/clientDefs/{your-entity-name}.json
    Code:
    {
        "menu": {
            "detail": {
                "buttons": [
                    "__APPEND__",
                    {
                        "label": "Recalculate Formula",
                        "name": "recalculateFormula",
                        "action": "recalculate",
                        "style": "default",
                        "acl": "edit",
                        "aclScope": "{your-entity-name}",
                        "data": {
                            "handler": "custom:unrestricted-recalculate-formula-handler"
                        },
                        "initFunction": "initRecalculate"
                    }
                ]
            }
        },
    }

    Step 6
    Clear cache and rebuild.
    The button should be visible in your entity's detail display as long as the user has "edit" privileges over that type of entity.
    You can use this capability in any other entity that you want, by repeating Step 5 for that specific entity.
    Last edited by telecastg; 02-20-2021, 10:03 PM.

    Leave a comment:


  • shalmaxb
    replied
    Hi, the button appears but when a normal user uses it, espoCRM throws a 403 forbidden. As yuri stated, recalculatin in the moment is not implemented for regular user. My question because of this is, if this script could change that behaviour.

    Leave a comment:


  • esforim
    replied
    I think changing the location of the button is not difficult, it sound like everything already working, you just need the button to appear for Everyone (all user or maybe just user with certain role). Currently this button only admin can see.

    Hope that clarify it.

    Leave a comment:

Working...