Zen two open - statistical report extension

Posted by lajkonik86 on Mon, 07 Feb 2022 13:59:01 +0100

  • Demand background:
    • Zen open source version does not have the function of report customization, but according to the needs of the test leader, it is necessary to count and master the demand realization rate of each project in the project dimension, so as to facilitate the construction of the model for reference in the follow-up work

Expansion effect

Documents & ideas involving modification


    • The old rules are expanded according to the expansion rules of Zen and Taoism
    • module/report/ext/lang/zh-cn/report_extend.php
    • report_extend.php is an extended font file with any name.

// FIXME adds the field of demand realization rate
$lang->report->projectStoryRate   = $lang->projectCommon . 'Summary of demand realization rate';

// FIXME makes statistics on the implementation of requirements according to the project status. Subdivided into in progress and closed
$lang->report->closedProject = 'Closed' . $lang->projectCommon;
$lang->report->processProject   = 'have in hand' . $lang->projectCommon;

// Add report type hyperlink to FIXME
$lang->reportList->project->lists[13] = $lang->projectCommon . 'Summary of demand realization rate|report|projectstoryrate';

// FIXME requirement realization rate field
$lang->report->storyRate = 'Demand realization rate';


    • Similarly, according to the rules, the extension directory is module / report / ext / control / projectstore php
    • At this time, the name cannot be arbitrarily named. The control class name corresponds to the rendered view name, that is, the control class name is consistent with the rendered front-end page name, as shown in the figure below

 * Create a bug.
 * @param  int    $productID
 * @param  string $branch
 * @param  string $extras       others params, forexample, projectID=10,moduleID=10
 * @access public
 * @return void
include '../../control.php';   // Introduce the native control class under the report module into
class myReport extends report  // The method under control is extended by inheritance and expansion
    /*  Add custom methods  */
     * Product information report.
     * @access public
     * @return void
    public function projectStoryRate($status = '')  // The name is arbitrary, the naming rules refer to the original control class, and the hump naming method is adopted
        // Font reading
        $this->app->loadLang('project');                // Read the font library under the project module
        $this->app->loadLang('story');                      // Read the word library under the story module
        $this->view->title      = $this->lang->report->projectStoryRate;  // Font value rendering to page - title
        $this->view->position[] = $this->lang->report->projectStoryRate;  // Controls the selection effect of the left sidebar.
        // The product query results are rendered to the front-end page and saved with the variable products, which can be directly referenced and queried in the view file ok
        $this->view->projects   = $this->report->getStoryRate($status);  //$this - > module name - > method name. This calling method is to directly call a method under the module
        $this->view->users      = $this->loadModel('user')->getPairs('noletter|noclosed'); // getPairs gets the user's key/value array
        $this->view->submenu    = 'project';   // It is passed to the submenu field in the view file to form the side navigation bar
        $this->view->status = $status;  // Query conditions are transmitted from the front end
        $this->display();  // Render to the corresponding view file, projectstoryrate html. php

Model & SQL writing

    • The method is called in the front control, then the model layer is expanded, and the rules are expanded according to the rules.
    • Path: module / report / ext / model / getstoryrate php
public function getStoryRate($status)
    // Write sql to query all project s, which are used for the front-end page display and value transfer
    // conditions are project_status
    // Ideas, according to project_status to filter and display the results.
     * Train of thought combing
     * Check all the project information, ok
     * Find the demand information of all projects, ok
     * The project information and demand information are combined into an array and returned to the front end. not yet

    $projects = $this->dao->select('*')->from(TABLE_PROJECT)
    // The demand information associated with the project is mainly the number
    zt_story as story
    left join zt_projectstory zp on story.id = zp.story
    left join zt_project as project on project.id = zp.project
    story.deleted = '0'
   project.name != ''
    // Query results in db
    // First, test in db to make sure there is no problem with sql, and then write it into a way recognized by Zen php. As follows, the official introduction of Zen is posted below
    // https://devel.easycorp.cn/book/extension/intro-45.html
    $storys =
        $this->dao->select('story.id,story.status,project.name,project.id as project')->from(TABLE_STORY)->alias('story')
            ->leftJoin(TABLE_PROJECTSTORY)->alias('zp')->on('story.id = zp.story')
            ->leftJoin(TABLE_PROJECT)->alias('project')->on('project.id = zp.project')
//            ->andWhere('project.id')->in($this->dao->select('id')->from(TABLE_PROJECT))->fi()
    foreach($storys as $story)
        // After traversing the obtained story result set, it needs to be associated with each item,
        // To put it simply, find all the requirements, find his father, and then form an array, pass it to the call, render it to the front-end view for processing
        // Shape such as
        // projects
                    - project  (There are no requirements for the current project)
              - project 
                 - storys
              - project 
                 - storys
        // Assign corresponding values to individual demand information and project information
        // How do requirements correspond to projects?
        foreach($projects as $project ){
            if ($story->name == $project->name ){
                // Judge whether it is the same item. If yes, it will be added to the story of the current item array
                // Here, you need to debug multiple times to determine whether the result is
                // Combine the item id in the previous statement with the item id in the array to get the result
                $projects[$story->project]->storys[$story->id] = $story;

//    return $products;
    return $projects;  // The use of callback, that is, the control layer



View view is written, supplemented by the missing js method

<?php include '../../../common/view/header.html.php';?>
<?php if(common::checkNotCN()):?>
    <style>#conditions .col-xs { width: 126px; }</style>
<?php endif;?>
<div id='mainContent' class='main-row'>
    <div class='side-col col-lg'>
        <?php include 'blockreportlist.html.php';?>

    <div class='main-col'>
        <?php if(empty($projects)):?>
            <div class="cell">
                <div class="table-empty-tip">
                    <p><span class="text-muted"><?php echo $lang->error->noData;?></span></p>
        <?php else:?>
            <div class='cell'>
                <div class='panel'>
                    <div class="panel-heading">
                        <div class="panel-title">
                            <div class="table-row" id='conditions'>
                                <div class="col-2"><?php echo $title;?></div>
                                <div class="col-xs text-right text-gray text-middle"><?php echo $lang->report->conditions?></div>
                                    <div class='col-xs input-group'>
                                        <span class='input-group-addon'><?php echo $lang->project->status;?></span>
                                        <?php echo html::select('status', $lang->project->statusList, $status , "class='form-control chosen ' onchange='changeParams(this)'");?>
                        <nav class="panel-actions btn-toolbar"></nav>
                    <div data-ride='table'>
                        <table class='table table-condensed table-striped table-bordered table-fixed no-margin' id='productList'>
<!--                                entry name-->
                                <th class='text-center w-200px'><?php echo $lang->project->name;?></th>
<!--                                team-->
                                <th class='text-center w-200px'><?php echo $lang->project->teamname;?></th>
                                <!--                                person liable-->
                                <th class='text-center w-70px'><?php echo $lang->project->owner;?></th>
<!--                                Stage of the project-->
                                <th class="text-center w-70px" ><?php echo $lang->project->projectStage;?></th>
<!--                                Project start time-->
                                <th  class="text-center w-100px"><?php echo $lang->projectCommon . $lang->project->begin;?></th>
<!--                                Project end time-->
                                <th class="text-center w-100px"><?php echo $lang->projectCommon . $lang->project->end;?></th>
<!--                                The requirement status is draft-->
                                <th class="text-center w-70px"><?php echo $lang->story->statusList['draft'];?></th>
<!--                                The demand status is active-->
                                <th class="text-center w-70px"><?php echo $lang->story->statusList['active'];?></th>
<!--                                The demand status is changed-->
                                <th class="text-center w-70px"><?php echo $lang->story->statusList['changed'];?></th>
<!--                                The demand status is closed-->
                                <th class="text-center w-70px"><?php echo $lang->story->statusList['closed'];?></th>
<!--                                Total number of demands-->
                                <th class="text-center w-70px"><?php echo $lang->report->total;?></th>
<!--                                The calculation formula of demand realization rate is the number of closed/Total number-->
                                <th class="text-center w-200px"><?php echo $lang->report->storyRate;?></th>

                            <?php $color = false;?>
<!--                            There is a problem in the initialization value, and repeated assignment should be considered-->

                            <?php foreach($projects as $project):?>
                                $closedCount = 0;
                                $activeCount = 0;
                                $changedCount = 0;
                                $draftCount = 0;
                                <tr class="text-center">
<!--                                    Project name created at the same time a Tab for click to jump-->
                                    <td class='text-center text-blue' title="<?php echo $project->name;?>" ><?php echo "<p>" . html::a($this->createLink('project', 'view', "project=$project->id"), $project->name) . "</p>";?></td>
<!--                                    Team-->
                                    <td class="<?php echo $class;?>"><?php echo $project->team;?></td>
                                    <!--                                    person in charge-->
                                    <td class="<?php echo $class;?>"><?php echo $project->PO;?></td>
<!--                                    Stage of the project-->
                                    <td class="<?php echo $class;?>"><?php echo $lang->project->projectStageList[$project->projectStage];?></td>
<!--                                    Project start date-->
                                    <td class="<?php echo $class;?>"><?php echo $project->begin == '2030-01-01' ? $lang->productplan->future : $project->begin;?></td>
<!--                                    Project deadline-->
                                    <td class="<?php echo $class;?>"><?php echo $project->end == '2030-01-01' ? $lang->productplan->future : $project->end;?></td>
                                    <!--                                    If the product plan is not empty-->

<!--                                    The original report is a product briefing, and the demand is linked to the plan,-->

                                        <?php foreach($project->storys as $story):?>
<!--                                        Statistics of demand quantity    -->
<!--                                        switch According to the status statistics, count ++  Then assign a value        -->
                                            switch ($story->status) {
                                                case "closed":
                                                case "active":
                                                case "changed":
                                                case "draft":
                                        <?php endforeach;?>
                                    <!--                                        Number of draft requirements -->
                                    <td class="<?php echo $class;?>"><?php echo $draftCount;?></td>
                                    <!--                                        Number of active demand status-->
                                    <td class="<?php echo $class;?>"><?php echo $activeCount;?></td>
                                    <!--                                        Number of changed requirements-->
                                    <td class="<?php echo $class;?>"><?php echo $changedCount;?></td>
                                    <!--                                        Number of closed demand status-->
                                    <td class="<?php echo $class;?>"><?php echo $closedCount;?></td>
                                    <!--                                        Statistics of total demand-->
                                    <td class="<?php echo $class;?>"><?php echo $draftCount + $activeCount + $changedCount + $closedCount;?></td>
                                    <!--                                        The decimal tail needs to be processed-->
                                    <td class="<?php echo $class;?>">
                                            $total = $draftCount + $changedCount + $closedCount + $activeCount;
//                                            If the total is not 0, it will enter the calculation, and if it is 0, it will directly return to the output 0
                                            if ($total!=0) {
                                                $rate = ($closedCount / $total) * 10000;
                                                $rate = floor($rate) / 10000 * 100 . "%";
                                                echo $rate;
                                                echo '0%';
                            <?php endforeach;?>

        <?php endif;?>
<?php include '../../../common/view/footer.html.php';?>
  • In the process of writing the view, you want to add a search condition and post the front-end code related to the search part and the required js code
  • The corresponding front-end page components are shown in the figure below
 <div class="panel-title">
                            <div class="table-row" id='conditions'>
                                <div class="col-2"><?php echo $title;?></div>
                                <div class="col-xs text-right text-gray text-middle"><?php echo $lang->report->conditions?></div>
                                    <div class='col-xs input-group'>
                                        <span class='input-group-addon'><?php echo $lang->project->status;?></span>
                                        <?php echo html::select('status', $lang->project->statusList, $status , "class='form-control chosen ' onchange='changeParams(this)'");?>
  • Fields will not be repeated. You can refer to the references to the font library in other view files and the records in previous articles.
  • You can notice that there is a js method in the select tag ο nchange='changeParams(this) ', called a js method, and the extension path is as follows
    • module/report/ext/js/projectstoryrate/projectstoryrate.js
  • content
function changeParams(obj)

    var status  = $('#conditions').find('#status').val();

    var link = createLink('report', 'projectStoryRate','status=' + status);

  • You can see that the above code is very simple. Get the block with id conditions in time, query the variable with id status in the block, and get the value
  • The focus is on the next step, createLink
  • Click the open source code to see that this method is a js method encapsulated by Zen. Its main function is to create a link, such as various jumps on Zen page. In fact, the bottom layer is mostly generated by this method call. Its calling method is also more intuitive.
  • Parameter interpretation,
    • report is the model name,
    • Do you remember the name projectStoryRate? It is the method name in the control class extended in this article,
    • status is the parameter to be passed. status is the parameter value that changes when the drop-down box is selected on the front page.
  • Call chain: front end user selection status - > ο nchange='changeParams(this) 'method - > createlink - > location href
  • To sum up, complete the query of different situations according to the status.


Conclusion: This article needs a certain experience foundation of the second open. If you have questions about the article, you can leave a message for communication.