123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791 |
- <?php
- namespace App\Http\Controllers;
- use App\Models\Pro;
- use App\Models\StatTreeLineClauseArg;
- use App\Models\StatTreeLineReportColumn;
- use Illuminate\Http\Request;
- use Illuminate\Support\Facades\Validator;
- use App\Models\Clause;
- use App\Models\StatTree;
- use App\Models\StatTreeLine;
- use App\Models\StatTreeLineClause;
- use Carbon\Carbon;
- use Illuminate\Support\Facades\DB;
- use Ramsey\Uuid\Uuid;
- class StatTreeController extends Controller
- {
- public function list()
- {
- $statTrees = StatTree::orderByRaw('is_template DESC NULLS LAST')->orderBy('name')->get();
- return view('app.stat-tree.stat-trees.list', compact('statTrees'));
- }
- public function createPage()
- {
- return view('app.stat-tree.stat-trees.create');
- }
- public function dashboard(StatTree $statTree)
- {
- return view('app.stat-tree.stat-trees.sub.dashboard', compact('statTree'));
- }
- public function dashboard2(StatTree $statTree)
- {
- return view('app.stat-tree.stat-trees.sub.dashboard2', compact('statTree'));
- }
- public function create(Request $request)
- {
- $validatedData = Validator::make($request->all(), [
- 'name' => 'required|string|unique:stat_tree',
- 'model' => 'required|string',
- 'slug' => 'required|string|unique:stat_tree'
- ]);
- if ($validatedData->fails()) return $this->fail($validatedData->errors()->first());
- [
- 'name' => $name,
- 'model' => $model,
- 'slug' => $slug
- ] = $request->all();
- $nextId = DB::select("select nextval('stat_tree_id_seq')");
- $statTree = new StatTree;
- $statTree->id = $nextId[0]->nextval;
- $statTree->uid = Uuid::uuid4();
- $statTree->name = $name;
- $statTree->model = $model;
- $statTree->slug = $slug;
- $statTree->is_template = (bool)$request->input('isTemplate');
- if($request->input('proUid')) {
- $pro = Pro::where('uid', $request->input('proUid'))->first();
- if($pro) {
- $statTree->pro_id = $pro->id;
- }
- }
- $statTree->pro_scope_clause = $request->input('proScopeClause');
- $statTree->save();
- return $this->pass($statTree->uid);
- }
- public function updateBasic(Request $request) {
- $statTree = StatTree::where('uid', $request->input('uid'))->first();
- if(!$statTree) return $this->fail('Stat tree not found!');
- $statTree->name = $request->input('name');
- $statTree->model = $request->input('model');
- $statTree->slug = $request->input('slug');
- $statTree->is_template = (bool)$request->input('isTemplate');
- $statTree->pro_id = NULL;
- if($request->input('proUid')) {
- $pro = Pro::where('uid', $request->input('proUid'))->first();
- if($pro) {
- $statTree->pro_id = $pro->id;
- }
- }
- $statTree->pro_scope_clause = $request->input('proScopeClause');
- $statTree->save();
- return $this->pass();
- }
- public function remove(Request $request) {
- $statTree = StatTree::where('uid', $request->input('uid'))->first();
- if(!$statTree) return $this->pass();
- DB::statement("DELETE FROM stat_tree_line WHERE stat_tree_id = :stat_tree_id", ['stat_tree_id' => $statTree->id]);
- DB::statement("DELETE FROM stat_tree_line_clause WHERE stat_tree_id = :stat_tree_id", ['stat_tree_id' => $statTree->id]);
- DB::statement("DELETE FROM stat_tree_line_clause_arg WHERE stat_tree_id = :stat_tree_id", ['stat_tree_id' => $statTree->id]);
- DB::statement("DELETE FROM stat_tree_line_clause_arg_value WHERE stat_tree_id = :stat_tree_id", ['stat_tree_id' => $statTree->id]);
- DB::statement("DELETE FROM stat_tree_line_report_column WHERE stat_tree_id = :stat_tree_id", ['stat_tree_id' => $statTree->id]);
- DB::statement("DELETE FROM stat_tree WHERE id = :stat_tree_id", ['stat_tree_id' => $statTree->id]);
- return $this->pass();
- }
- public function instantiate(Request $request, StatTree $statTree) {
- if(!$statTree->is_template) {
- return $this->fail("State tree is not a template!");
- }
- $pro = Pro::where('uid', $request->input('proUid'))->first();
- if(!$pro) {
- return $this->fail("Pro not found!");
- }
- $instance = $statTree->instantiateForPro($pro);
- return $this->pass($instance->uid);
- }
- public function clone(Request $request, StatTree $statTree) {
- $instance = $statTree->clone($request->input('name'));
- return $this->pass($instance->uid);
- }
- private function traverseLines($_lines, &$result) {
- foreach ($_lines as $line) {
- $result[] = $line;
- if(count($line->children)) {
- $this->traverseLines($line->children, $result);
- }
- }
- }
- public function edit(Request $request, StatTree $statTree) {
- $linesFlat = [];
- if($request->input('multi-pro')) {
- $this->traverseLines($statTree->rootLines, $linesFlat);
- }
- return view('app.stat-tree.stat-trees.sub.edit', compact('statTree', 'linesFlat'));
- }
- public function replaceAllLines(Request $request){
- $parents = [];
- $columns = '';
- $statTreeID = (int) $request->get('statTreeID');
- $data = $request->get('data');
- $rows = json_decode($data, true);
- $statTree = StatTree::where('id', $statTreeID)->first();
- $model = $statTree->model;
- DB::beginTransaction();
- // cleanup junk
- DB::statement("DELETE FROM stat_tree_line WHERE stat_tree_id = :stat_tree_id", ['stat_tree_id' => $statTree->id]);
- DB::statement("DELETE FROM stat_tree_line_clause WHERE stat_tree_id = :stat_tree_id", ['stat_tree_id' => $statTree->id]);
- DB::statement("DELETE FROM stat_tree_line_clause_arg WHERE stat_tree_id = :stat_tree_id", ['stat_tree_id' => $statTree->id]);
- DB::statement("DELETE FROM stat_tree_line_clause_arg_value WHERE stat_tree_id = :stat_tree_id", ['stat_tree_id' => $statTree->id]);
- DB::statement("DELETE FROM stat_tree_line_report_column WHERE stat_tree_id = :stat_tree_id", ['stat_tree_id' => $statTree->id]);
- for($x = 0; $x < count($rows); $x++){
- $row = $rows[$x];
- $nextStatLineId = DB::select("select nextval('stat_tree_line_id_seq')");
- $statTreeLine = new StatTreeLine;
- $statTreeLine->id = $nextStatLineId[0]->nextval;
- $statTreeLine->uid = Uuid::uuid4();
- $statTreeLine->stat_tree_id = $statTree->id;
- $statTreeLine->tree_order_position_index = $x;
- $statTreeLine->last_refresh_count = null;
- $statTreeLine->tsv_text_for_report_columns = null;
- $statTreeLine->save();
- $allClauses = [];
- for($i = 0; $i < count($row); $i++){
- $cell = $row[$i];
- if(!$cell || empty($cell)) continue;
- $parts = explode('==>', $cell);
- $cell = $parts[0];
- $columns = count($parts) > 1 ? $parts[1] : '';
- $clause = Clause::where('label', $cell)->where('model', 'ilike', $model)->first();
- if(!$clause){
- DB::rollBack();
- return $this->fail('No clause record found for ' . $cell);
- }
- $nextStatLineClauseId = DB::select("select nextval('stat_tree_line_clause_id_seq')");
- $statTreeLineClause = new StatTreeLineClause;
- $statTreeLineClause->id = $nextStatLineClauseId[0]->nextval;
- $statTreeLineClause->uid = Uuid::uuid4();
- $statTreeLineClause->stat_tree_line_id = $statTreeLine->id;
- $statTreeLineClause->clause_id = $clause->id;
- $statTreeLineClause->clause_label = $cell;
- $statTreeLineClause->position_index = $i;
- $statTreeLineClause->detail_json = json_encode(['model' => $model]);
- $statTreeLineClause->stat_tree_id = $statTree->id;
- $statTreeLineClause->save();
- // check if the clause has any clauseArgs, if yes, create stat-tree-line-clause-arg and value records for them
- if(count($clause->clauseArgs)) {
- foreach ($clause->clauseArgs as $clauseArg) {
- $statTreeLineClauseArg = new StatTreeLineClauseArg();
- $nextId = DB::select("select nextval('stat_tree_line_clause_arg_id_seq')");
- $statTreeLineClauseArg->id = $nextId[0]->nextval;
- $statTreeLineClauseArg->stat_tree_line_clause_id = $statTreeLineClause->id;
- $statTreeLineClauseArg->clause_arg_id = $clauseArg->id;
- $statTreeLineClauseArg->access_level = 'ADMIN';
- $statTreeLineClauseArg->stat_tree_id = $statTree->id;
- $statTreeLineClauseArg->value = null;
- // TODO: need to copy clause arg values from parent node for all except last clause
- $statTreeLineClauseArg->save();
- }
- }
- $allClauses[] = $cell;
- // fill report columns (if last clause)
- if($i === count($row) - 1 && !!$columns) {
- $columns = explode(",", $columns);
- for ($j = 0; $j < count($columns); $j++) {
- $parts = explode("|", $columns[$j]);
- $column = new StatTreeLineReportColumn();
- $nextId = DB::select("select nextval('stat_tree_line_report_column_id_seq')");
- $column->id = $nextId[0]->nextval;
- $column->uid = Uuid::uuid4();
- $column->stat_tree_line_id = $statTreeLine->id;
- $column->label = $parts[1];
- $column->display_key = $parts[0];
- $positionIndex = DB::select("select max(position_index) from stat_tree_line_report_column where stat_tree_line_id = {$column->stat_tree_line_id}");
- $column->position_index = is_numeric($positionIndex[0]->max) ? $positionIndex[0]->max + 1 : 1;
- $column->stat_tree_id = $statTree->id;
- $column->save();
- }
- }
- }
- $parents[implode("|", $allClauses)] = $statTreeLine;
- // if child, find and set parent
- $nonEmpty = [];
- for($i = 0; $i < count($row); $i++){
- if($row[$i] && !empty($row[$i])) $nonEmpty[] = $row[$i];
- }
- if(count($nonEmpty) > 1) {
- $parentClauses = [];
- for($i = 0; $i < count($nonEmpty) - 1; $i++){
- $cell = $nonEmpty[$i];
- $parts = explode('==>', $cell);
- $cell = $parts[0];
- $columns = count($parts) > 1 ? $parts[1] : '';
- $clause = Clause::where('label', $cell)->where('model', 'ilike', $model)->first();
- if(!$clause){
- DB::rollBack();
- return $this->fail('No clause record found for ' . $cell);
- }
- $parentClauses[] = $clause->label;
- }
- $parentClauses = implode("|", $parentClauses);
- if(@$parents[$parentClauses]) {
- $statTreeLine->parent_stat_tree_line_id = $parents[$parentClauses]->id;
- $statTreeLine->save();
- }
- }
- }
- DB::commit();
- return $this->pass();
- }
- public function clausesJSON(Request $request, StatTree $statTree) {
- $clauses = Clause::where('model', $statTree->model)->orderBy('label')->get();
- $nodes = [];
- foreach ($clauses as $clause) {
- $children = [];
- // clause text child
- $children[] = [
- "text" => $clause->clause_text,
- "icon" => "fa fa-laptop-code text-primary text-sm",
- "state" => [
- "opened" => false,
- "disabled" => false,
- "selected" => false,
- ],
- "li_attr" => [
- "type" => "clause_text"
- ],
- "a_attr" => [
- "title" => $clause->clause_text,
- ],
- "data" => [
- "type" => "clause_text"
- ]
- ];
- // clause arg children
- $argsSystem = [];
- foreach ($clause->clauseArgs as $clauseArg) {
- $children[] = [
- "text" => $clauseArg->arg_text . '<span class="text-secondary text-sm ml-2">' . $clauseArg->field_type . '</span>',
- "icon" => "fa fa-cubes text-info",
- "state" => [
- "opened" => false,
- "disabled" => false,
- "selected" => false,
- ],
- "data" => [
- "type" => "clause_arg",
- "id" => $clauseArg->id,
- "uid" => $clauseArg->uid,
- "argText" => $clauseArg->arg_text,
- "fieldType" => $clauseArg->field_type,
- "clauseId" => $clause->id
- ]
- ];
- $argsSystem[] = [
- "arg_text" => $clauseArg->arg_text,
- "field_type" => $clauseArg->field_type,
- "value" => null,
- "access_level" => null
- ];
- }
- $nodes[] = [
- "text" => $clause->label,
- "state" => [
- "opened" => false,
- "disabled" => false,
- "selected" => false,
- ],
- "children" => $children,
- "data" => [
- "type" => "clause",
- "id" => $clause->id,
- "uid" => $clause->uid,
- "model" => $clause->model,
- "question" => $clause->question,
- "answer" => $clause->answer,
- "label" => $clause->label,
- "clauseText" => $clause->clause_text,
- "clauseId" => $clause->id,
- "args" => $argsSystem
- ],
- "a_attr" => [
- "title" => $clause->clause_text,
- ],
- ];
- }
- return json_encode($nodes);
- }
- private function cleanupClause($clauseText)
- {
- //Dont include empty clauses, i.e ()
- preg_match('#\((.*?)\)#', $clauseText, $match);
- $content = @$match[1];
- if (!$content || empty($content)) return null;
- return $content;
- }
- private function applyStatTreeLineQueryClauses(StatTreeLine $statTreeLine, $proUid = false, $allInputs = [])
- {
- $model = $statTreeLine->statTree->model;
- $clauses = [];
- foreach ($statTreeLine->lineClauses as $lineClause) {
- $clauseText = $lineClause->clause->clause_text;
- // apply arg values
- foreach ($lineClause->clause->clauseArgs as $clauseArg) {
- $value = null;
- foreach ($lineClause->lineClauseArgs as $lineClauseArg) {
- if($lineClauseArg->clause_arg_id === $clauseArg->id) {
- $value = $lineClauseArg->value;
- }
- }
- // if override available - replace with that
- if(@$allInputs['st__' . $clauseArg->arg_text]) {
- $value = $allInputs['st__' . $clauseArg->arg_text];
- }
- if(!is_null($value)) {
- $clauseText = str_replace(
- ':' . $clauseArg->arg_text, // search for :xxx
- "'" . $value . "'::" . $clauseArg->field_type, // replace with '$value'::$field_type
- $clauseText);
- }
- }
- //dump($clauseText);
- /*$isValid = $this->cleanupClause($clauseText);
- if ($isValid) {*/
- array_push($clauses, $clauseText);
- //}
- }
- // if stat tree bound to a pro, apply pro_scope_clause
- if(!$proUid) {
- if($statTreeLine->statTree->pro && $statTreeLine->statTree->pro_scope_clause) {
- $clauses[] = str_replace('@PRO_ID', $statTreeLine->statTree->pro->id, $statTreeLine->statTree->pro_scope_clause);
- }
- }
- else {
- $mvPro = Pro::where('uid', $proUid)->first();
- if($statTreeLine->statTree->pro_scope_clause) {
- $clauses[] = str_replace('@PRO_ID', $mvPro->id, $statTreeLine->statTree->pro_scope_clause);
- }
- }
- $query = 'SELECT COUNT(*) FROM '.$model.' WHERE '. implode(" AND ", $clauses);
- try {
- //dump($query);
- $result = DB::select($query);
- }
- catch (\Exception $ex) {
- $result = 'error';
- }
- return $result;
- }
- private function applyStatTreeLineQueryClausesGroupByPros(StatTreeLine $statTreeLine, $proUids)
- {
- $model = $statTreeLine->statTree->model;
- $clauses = [];
- foreach ($statTreeLine->lineClauses as $lineClause) {
- $clauseText = $lineClause->clause->clause_text;
- // apply arg values
- foreach ($lineClause->clause->clauseArgs as $clauseArg) {
- $value = null;
- foreach ($lineClause->lineClauseArgs as $lineClauseArg) {
- if($lineClauseArg->clause_arg_id === $clauseArg->id) {
- $value = $lineClauseArg->value;
- }
- }
- if(!is_null($value)) {
- $clauseText = str_replace(
- ':' . $clauseArg->arg_text, // search for :xxx
- "'" . $value . "'::" . $clauseArg->field_type, // replace with '$value'::$field_type
- $clauseText);
- }
- }
- //dump($clauseText);
- /*$isValid = $this->cleanupClause($clauseText);
- if ($isValid) {*/
- array_push($clauses, $clauseText);
- //}
- }
- // if stat tree bound to a pro, apply pro_scope_clause
- /*if(!$proUid) {
- if($statTreeLine->statTree->pro && $statTreeLine->statTree->pro_scope_clause) {
- $clauses[] = str_replace('@PRO_ID', $statTreeLine->statTree->pro->id, $statTreeLine->statTree->pro_scope_clause);
- }
- }
- else {
- $mvPro = Pro::where('uid', $proUid)->first();
- if($statTreeLine->statTree->pro_scope_clause) {
- $clauses[] = str_replace('@PRO_ID', $mvPro->id, $statTreeLine->statTree->pro_scope_clause);
- }
- $query = 'SELECT COUNT(*) FROM '.$model.' WHERE '. implode(" AND ", $clauses);
- }*/
- $proUids = explode(",", $proUids);
- $proUids = array_map(function($_x) {
- return "'{$_x}'";
- }, $proUids);
- $clauses[] = "_j_pro.uid IN (" . implode(",", $proUids) . ")";
- $proJoinClause = 'JOIN pro _j_pro on ' . str_replace('@PRO_ID', '_j_pro.id', $statTreeLine->statTree->pro_scope_clause);
- $query = "SELECT COUNT(*), _j_pro.uid as _v_pro_uid FROM {$model} {$proJoinClause} WHERE " . implode(" AND ", $clauses) . " GROUP BY _j_pro.uid";
- try {
- //dump($query);
- $result = DB::select($query);
- }
- catch (\Exception $ex) {
- $result = 'error';
- }
- return $result;
- }
- public function linesJSON(Request $request, StatTree $statTree) {
- // refresh counts
- $lines = $statTree->lines;
- foreach ($lines as $line) {
- $query = $this->applyStatTreeLineQueryClauses($line, $request->input('proUid'), $request->input());
- if ($query && $query !== 'error') {
- $line->last_refresh_count = $query[0]->count;
- }
- else {
- $line->last_refresh_count = -1;
- }
- $line->save();
- }
- $nodes = [];
- foreach ($statTree->rootLines as $rootLine) {
- $nodes[] = $this->lineObject($rootLine);
- }
- return json_encode($nodes);
- }
- public function getCountsForPro(Request $request) {
- $statTreeUid = $request->get('uid');
- if (!$statTreeUid) return $this->fail('No specified stat tree!');
- $statTree = StatTree::where('uid', $statTreeUid)->first();
- $lines = $statTree->lines;
- $result = [];
- foreach ($lines as $line) {
- $query = $this->applyStatTreeLineQueryClauses($line, $request->input('proUid'));
- if ($query && $query !== 'error') {
- $result[$line->uid] = $query[0]->count;
- }
- else {
- $result[$line->uid] = -1;
- }
- }
- return json_encode($result);
- }
- public function getCountsForPros(Request $request) {
- $statTreeUid = $request->get('uid');
- if (!$statTreeUid) return $this->fail('No specified stat tree!');
- $statTree = StatTree::where('uid', $statTreeUid)->first();
- $lines = $statTree->lines;
- $result = [];
- foreach ($lines as $line) {
- $query = $this->applyStatTreeLineQueryClausesGroupByPros($line, $request->input('proUids'));
- if ($query && $query !== 'error') {
- $result[$line->uid] = $query;
- }
- else {
- $result[$line->uid] = -1;
- }
- }
- return json_encode($result);
- }
- private function lineObject(StatTreeLine $line) {
- // columns
- $columns = [];
- foreach ($line->reportColumns as $column) {
- $columns[] = [
- "label" => $column->label,
- "display_key" => $column->display_key,
- "type" => $column->field_type
- ];
- }
- // clause
- $lineClause = $line->displayLineClause();
- $args = [];
- $argsLabel = [];
- foreach($lineClause->lineClauseArgs as $stlcArg) {
- if($stlcArg->clauseArg) {
- $args[] = [
- "arg_text" => $stlcArg->clauseArg->arg_text,
- "field_type" => $stlcArg->clauseArg->field_type,
- "value" => $stlcArg->value,
- "access_level" => $stlcArg->access_level
- ];
- $argsLabel[] = $stlcArg->clauseArg->arg_text . ': ' . $stlcArg->value;
- }
- }
- $clause = [
- "clause_id" => $lineClause->clause_id,
- "clause_label" => $lineClause->clause_label,
- "position_index" => $lineClause->position_index,
- "args" => $args
- ];
- $children = [];
- foreach ($line->children as $child) {
- $children[] = $this->lineObject($child);
- }
- return [
- "text" => '<span class="stat-tree-anchor">' .
- '<span class="text-secondary text-sm">' . ($line->tree_order_position_index + 1) . '.</span> ' .
- $line->displayLabel() . '</span>' .
- (count($argsLabel) ? '<span class="arg-label text-info text-sm ml-2">[' . implode(', ', $argsLabel) . ']</span>' : '') .
- '<span class="ml-2 text-secondary line-count-label">(' .
- (is_null($line->last_refresh_count) ? '…' :
- ($line->last_refresh_count === -1 ?
- '<span class="text-danger text-sm font-weight-bold"><i class="fa fa-exclamation-triangle"></i> Query error / missing arg values</span>' :
- $line->last_refresh_count)) .
- ')</span>',
- "state" => [
- "opened" => true,
- "disabled" => false,
- "selected" => false,
- ],
- "children" => $children,
- "data" => [
- "type" => "stat_tree_line",
- "id" => $line->id,
- "uid" => $line->uid,
- "displayLabel" => $line->displayLabel(),
- "extendedLabel" => $line->displayLabel() . (count($argsLabel) ? ' [' . implode(', ', $argsLabel) . ']' : ''),
- "lastRefreshCount" => $line->last_refresh_count,
- "treeOrderPositionIndex" => $line->tree_order_position_index,
- "columns" => $columns,
- "clause" => $clause,
- "goalPercent" => (is_null($line->goal_percent) ? -1 : $line->goal_percent),
- "goalCondition" => (is_null($line->goal_condition) ? '' : $line->goal_condition)
- ],
- "a_attr" => [
- "title" => $line->displayLineClause()->clause->clause_text
- ]
- ];
- }
- public function replaceAllLinesJSON(Request $request) {
- $statTree = StatTree::where('uid', $request->get('uid'))->first();
- if(!$statTree) return $this->fail("Stat tree does not exist!");
- $lines = json_decode($request->get('data'));
- DB::beginTransaction();
- // cleanup junk
- DB::statement("DELETE FROM stat_tree_line WHERE stat_tree_id = :stat_tree_id", ['stat_tree_id' => $statTree->id]);
- DB::statement("DELETE FROM stat_tree_line_clause WHERE stat_tree_id = :stat_tree_id", ['stat_tree_id' => $statTree->id]);
- DB::statement("DELETE FROM stat_tree_line_clause_arg WHERE stat_tree_id = :stat_tree_id", ['stat_tree_id' => $statTree->id]);
- DB::statement("DELETE FROM stat_tree_line_clause_arg_value WHERE stat_tree_id = :stat_tree_id", ['stat_tree_id' => $statTree->id]);
- DB::statement("DELETE FROM stat_tree_line_report_column WHERE stat_tree_id = :stat_tree_id", ['stat_tree_id' => $statTree->id]);
- // process
- for ($i=0; $i<count($lines); $i++) {
- $result = $this->saveStatTreeLine($lines[$i], $i, null, $statTree);
- if($result !== TRUE) {
- DB::rollBack();
- return $result;
- }
- }
- DB::commit();
- return $this->pass();
- }
- private function saveStatTreeLine($line, $position, $parentLine, $statTree) {
- // saved tree line
- $nextId = DB::select("select nextval('stat_tree_line_id_seq')");
- $statTreeLine = new StatTreeLine;
- $statTreeLine->id = $nextId[0]->nextval;
- $statTreeLine->uid = Uuid::uuid4();
- $statTreeLine->stat_tree_id = $statTree->id;
- $statTreeLine->tree_order_position_index = $position;
- $statTreeLine->last_refresh_count = null;
- $statTreeLine->tsv_text_for_report_columns = null;
- $statTreeLine->goal_condition = (!@$line->goalCondition ? null : $line->goalCondition);
- $statTreeLine->goal_percent = (!@$line->goalPercent || $line->goalPercent === -1 ? null : $line->goalPercent);
- $statTreeLine->parent_stat_tree_line_id = $parentLine ? $parentLine->id : null;
- $statTreeLine->save();
- // -- clauses -- START
- // copy parent line clauses
- $maxParentClausePositionIndex = 0;
- if($parentLine && count($parentLine->lineClauses)) {
- foreach ($parentLine->lineClauses as $parentLineClause) {
- $nextId = DB::select("select nextval('stat_tree_line_clause_id_seq')");
- $statTreeLineClause = new StatTreeLineClause();
- $statTreeLineClause->id = $nextId[0]->nextval;
- $statTreeLineClause->uid = Uuid::uuid4();
- $statTreeLineClause->stat_tree_line_id = $statTreeLine->id; // this stat tree line
- $statTreeLineClause->clause_id = $parentLineClause->clause_id;
- $statTreeLineClause->clause_label = $parentLineClause->clause_label;
- $statTreeLineClause->position_index = $parentLineClause->position_index;
- if($statTreeLineClause->position_index > $maxParentClausePositionIndex) {
- $maxParentClausePositionIndex = $statTreeLineClause->position_index;
- }
- $statTreeLineClause->stat_tree_id = $statTree->id;
- $statTreeLineClause->save();
- // copy clause args for parent line clauses
- foreach ($parentLineClause->lineClauseArgs as $parentLineClauseArg) {
- $statTreeLineClauseArg = new StatTreeLineClauseArg();
- $nextId = DB::select("select nextval('stat_tree_line_clause_arg_id_seq')");
- $statTreeLineClauseArg->id = $nextId[0]->nextval;
- $statTreeLineClauseArg->stat_tree_line_clause_id = $statTreeLineClause->id; // this line cause
- $statTreeLineClauseArg->clause_arg_id = $parentLineClauseArg->clause_arg_id;
- $statTreeLineClauseArg->value = $parentLineClauseArg->value;
- $statTreeLineClauseArg->access_level = $parentLineClauseArg->access_level;
- $statTreeLineClauseArg->stat_tree_id = $statTree->id;
- $statTreeLineClauseArg->save();
- }
- }
- }
- // create own line clause (from clause.clause_label)
- $clause = Clause::where('label', $line->clause->clause_label)->where('model', 'ilike', $statTree->model)->first();
- if(!$clause) {
- return $this->fail('No clause record found for ' . $line->clause->clause_label);
- }
- $nextId = DB::select("select nextval('stat_tree_line_clause_id_seq')");
- $statTreeLineClause = new StatTreeLineClause();
- $statTreeLineClause->id = $nextId[0]->nextval;
- $statTreeLineClause->uid = Uuid::uuid4();
- $statTreeLineClause->stat_tree_line_id = $statTreeLine->id; // this stat tree line
- $statTreeLineClause->clause_id = $clause->id;
- $statTreeLineClause->clause_label = $line->clause->clause_label;
- $statTreeLineClause->position_index = $maxParentClausePositionIndex + 1;
- $statTreeLineClause->stat_tree_id = $statTree->id;
- $statTreeLineClause->save();
- // create args for own line clause
- foreach ($clause->clauseArgs as $clauseArg) {
- $statTreeLineClauseArg = new StatTreeLineClauseArg();
- $nextId = DB::select("select nextval('stat_tree_line_clause_arg_id_seq')");
- $statTreeLineClauseArg->id = $nextId[0]->nextval;
- $statTreeLineClauseArg->stat_tree_line_clause_id = $statTreeLineClause->id;
- $statTreeLineClauseArg->clause_arg_id = $clauseArg->id;
- $statTreeLineClauseArg->value = null;
- $statTreeLineClauseArg->access_level = 'ADMIN';
- for ($j=0; $j<count($line->clause->args); $j++) { // find the arg matching text and type from line->args and use that
- if($line->clause->args[$j]->arg_text === $clauseArg->arg_text &&
- $line->clause->args[$j]->field_type === $clauseArg->field_type) {
- $statTreeLineClauseArg->value = $line->clause->args[$j]->value;
- $statTreeLineClauseArg->access_level = $line->clause->args[$j]->access_level;
- break;
- }
- }
- $statTreeLineClauseArg->stat_tree_id = $statTree->id;
- $statTreeLineClauseArg->save();
- }
- // -- clauses -- END
- // columns
- for ($i=0; $i<count($line->columns); $i++) {
- $column = new StatTreeLineReportColumn();
- $nextId = DB::select("select nextval('stat_tree_line_report_column_id_seq')");
- $column->id = $nextId[0]->nextval;
- $column->uid = Uuid::uuid4();
- $column->stat_tree_line_id = $statTreeLine->id;
- $column->label = $line->columns[$i]->label;
- $column->display_key = $line->columns[$i]->display_key;
- $column->field_type = $line->columns[$i]->type;
- $column->position_index = $i;
- $column->stat_tree_id = $statTree->id;
- $column->save();
- }
- // child lines
- for ($i=0; $i<count($line->children); $i++) {
- $result = $this->saveStatTreeLine($line->children[$i], $i, $statTreeLine, $statTree);
- if($result !== TRUE) {
- DB::rollBack();
- return $result;
- }
- }
- return TRUE;
- }
- public function refreshTreeCountQueries(Request $request)
- {
- $statTreeID = $request->get('statTreeID');
- if (!$statTreeID) return $this->fail('No specified stat tree!');
- $statTree = StatTree::where('id', $statTreeID)->first();
- if (!$statTree) return $this->fail('Invalid stat tree!');
- $lines = $statTree->lines;
- foreach ($lines as $line) {
- $query = $this->applyStatTreeLineQueryClauses($line);
- if ($query && $query !== 'error') {
- $line->last_refresh_count = $query[0]->count;
- }
- else {
- $line->last_refresh_count = -1;
- }
- $line->save();
- }
- return $this->pass();
- }
- }
|