meraproject/themes/merakomis/fot/controller.php
keboss-m 5c21d25d45 Initial commit: Merakomis portal, Docker stack and user-reader API.
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-24 11:04:05 +03:00

444 lines
14 KiB
PHP

<?
namespace controller\themes\merakomis\fot;
use core\core\structure\eRowClick;
use Mpdf\Tag\Q;
use ms\ms\structure\msControllerTable;
use themes\Merakomis;
use themes\merakomis\dictionary\City;
use themes\merakomis\dictionary\Department;
use themes\merakomis\dictionary\Org;
use themes\merakomis\dictionary\OrgType;
use themes\merakomis\dictionary\Staffing;
use themes\merakomis\Emp;
use themes\merakomis\Fot;
use themes\merakomis\fot\Budget;
use themes\merakomis\fot\structure\eFotStatus;
use themes\merakomis\Project;
use themes\merakomis\structure\merakomisControllerTable;
use themes\merakomis\Time;
class Api extends merakomisControllerTable {
static $class = 'themes\merakomis\fot';
public function importFile(){
exit;
set_time_limit(0);
//Fot::delete();
$f = fopen(__DIR__.'/import.csv','r');
$first = fgetcsv($f,null,";");
$months = [];
for($i=2;$i<count($first);$i++){
$m = trim($first[$i]);
if(!$m) continue;
$months[] = $first[$i];
}
$data = [];
while($s = fgetcsv($f,null,";")) {
$id = $s[0];
$name = $s[1];
for($i=2;$i<count($months)+2;$i++){
$m = $i-2;
$value = intval(trim($s[$i]));
if($value){
$data[$id][$months[$m]] = $value;
}
}
}
foreach ($data as $id=>$arr) {
foreach ($arr as $month=>$value) {
$d = explode('.',$month);
Fot::insert([
Fot::$EMP=>$id,
Fot::$YEAR=>2000+intval($d[1]),
Fot::$MONTH=>intval($d[0]),
Fot::$FZP=>$value
]);
file_put_contents(__DIR__.'/report.txt',$id.':'.$m."\n",FILE_APPEND);
}
}
foreach ($months as $m){
file_put_contents(__DIR__.'/report.txt',$m."\n",FILE_APPEND);
$d = explode('.',$m);
Fot::generate(2000+intval($d[1]),intval($d[0]));
}
}
public function encrypt(){
$a = Fot::getAll();
foreach ($a as $x) {
Fot::updateById($x[Fot::$ID],$x);
}
}
public function updateFromTable()
{
$res = $_POST;
$id = intval($_POST['id']);
$data = [
Fot::$STATUS => eFotStatus::WORK,
];
switch($_POST['type']) {
case 'fzp':
$data[Fot::$FZP] = cfloatval($_POST['value']);
break;
case 'add':
$data[Fot::$ADD] = cfloatval($_POST['value']);
break;
}
$r = Fot::updateById($id,$data);
$x = Fot::getById($id);
Budget::mathByYearMonth($x[Fot::$YEAR], $x[Fot::$MONTH]);
//Fot::math($id);
$res['res'] = $r;
$res['data'] = $data;
echo je($res);
}
public function import()
{
$filter = $_POST['filter'];
$res = [];
$nowYear = $year = intval($_POST['year']?:date('Y'));
$nowMonth = $month = intval($_POST['month']?:date('m'));
$name = trim($_POST['name']?:'');
$isBad = boolval($_POST['mark']);
$time = strtotime($year.'-'.$month.'-01');
$prevTime = strtotime("-1 month", $time);
$prevYear = date('Y', $prevTime);
$prevMonth = date('n', $prevTime);
$res['send'] = [
'$year'=>$year,
'$month'=>$month,
'$name'=>$name,
'$isBad'=>$isBad,
];
$res['year'] = $year;
$res['month'] = $month;
$res['prevYear'] = $prevYear;
$res['prevMonth'] = $prevMonth;
$res['budget'] = [
'other'=>0,
'edit'=>0,
'id'=>0,
'mark'=>'',
];
$periods = [
[$year,$month],
[$prevYear,$prevMonth],
];
$b1 = Budget::get($year,$month);
$b2 = Budget::get($prevYear,$prevMonth);
Fot::generate($year,$month);
Fot::generate($prevYear,$prevMonth);
$budget['id'] = $b1[Budget::$ID];
$budget['edit'] = $b1[Budget::$MONEY];
$budget['mark'] = !($b1[Budget::$MONEY]==$b2[Budget::$MONEY]); //boolval($b1[Budget::$CHANGED]);
$budget['other'] = $b2[Budget::$MONEY];
$res['budget'] =$budget;
$filter_text = [];
$emp_and = [];
if($filter[$c ='name']) {
$emp_and[] = \Where::_operator(Emp::$NAME,'LIKE','%'.$filter[$c].'%');
$filter_text[] = 'Имя: «'.$filter[$c].'»';
}
if(is_numeric($filter[$c ='city']) and $filter[$c]>0) {
$emp_and[] = \Where::_operator(Emp::$CITY,'=',intval($filter[$c]));
$filter_text[] = City::getName( City::getByID($filter[$c]) );
}
if(is_numeric($filter[$c ='org']) and $filter[$c]>0) {
$emp_and[] = \Where::_operator(Emp::$ORG,'=',intval($filter[$c]));
$filter_text[] = Org::getName( Org::getByID($filter[$c]) );
}
if(is_numeric($filter[$c ='orgtype']) and $filter[$c]>0) {
$emp_and[] = \Where::_operator(Emp::$ORG_TYPE,'=',intval($filter[$c]));
$filter_text[] = OrgType::getName( OrgType::getByID($filter[$c]) );
}
$structure = Department::getStructure();
if(is_numeric($filter[$c ='department']) and $filter[$c]>0) {
$dep_emp_ids = $structure['base'][$filter[$c]]['emp_ids'];
$emp_and[] = \Where::_in(Emp::$ID,$dep_emp_ids?:[0]);
$filter_text[] = Department::getName( $structure['base'][$filter[$c]] );
}
if(is_numeric($filter[$c ='staffing']) and $filter[$c]>0) {
$emp_and[] = \Where::_operator(Emp::$STAFFING,'LIKE','%"'.$filter[$c].'"%') ;
$filter_text[] = Staffing::getName( Staffing::getByID(intval($filter[$c])) );;
}
if(is_numeric($filter[$c ='freelance']) and $filter[$c]>=0) {
$emp_and[] = \Where::_operator(Emp::$IS_FREELANCER,'=',$filter[$c]);
$filter_text[] = Staffing::getName( Staffing::getByID(intval($filter[$c])) );;
}
$data = [];
$beginDate = $year.'-'.($month<10?'0':'').$month.'-01';
$endDate = date('Y-m-d',strtotime($beginDate.' + 1 month - 1 day'));
foreach($periods as $k=>$period) {
$isSecond = $k==1;
$year = $period[0];
$month = $period[1];
$and = $emp_and;
$and[] = \Where::_operator(Fot::$YEAR, '=', $year);
$and[] = \Where::_operator(Fot::$MONTH, '=', $month);
if ($name) $and[] = \Where::_or([
\Where::_operator(Fot::$NAME, 'like', '%' . $name . '%'),
\Where::_operator(Emp::$NAME, 'like', '%' . $name . '%'),
]);
$and[] = Time::getEmpWhereAnd($beginDate, $endDate);
/*
$and[] = \Where::_inQuery(Emp::$ID,[
\Query::TABLES => [Time::$table_name],
\Query::SELECT => ['DISTINCT '.Emp::$ID],
\Query::WHERE => new \Where(\Where::_and([
\Where::_between(Time::$DATE,$beginDate,$endDate),
]))
]);
*/
// if ($isBad) $and[] = \Where::_operator(Fot::$STATUS, '=', eFotStatus::NONE);
$r = Fot::select($q = [
\Query::LEFT_JOINS => [
[Emp::$table_name, Emp::$ID, Fot::$EMP],
],
\Query::WHERE => new \Where(\Where::_and($and)),
\Query::COUNT => 0,
]);
$cities = City::getAll();
$res['q'][] = (string)new \Query($q);
while ($l = \DB::fetch($r)) {
Fot::decrypt($l);
$emp_id = $l[Fot::$EMP];
$color = (($l[Fot::$STATUS])?'#1c303b':'#fb4f14');
$isBadFot = ($l[Fot::$STATUS] == eFotStatus::NONE);
$data[$emp_id][$year.$month] = [
'id'=>intval($l[Fot::$ID]),
'emp_id'=>intval($l[Fot::$EMP]),
'name'=>Emp::SurnameIO($l),
'name2'=>$l[Fot::$NAME],
'fzp'=>$l[Fot::$FZP],
'add'=>$l[Fot::$ADD],
'fot'=>$l[Fot::$FOT],
'per_hour'=>$l[Fot::$PER_HOUR],
'archive'=>boolval($l[Emp::$ARCHIVE]),
//'mark'=>eFotStatus::getName($l[Fot::$STATUS]),
//'color'=>$color,
'location'=>City::getName( City::getByIDCached(intval($l[Emp::$CITY])) ),
'freelance'=>($l[Emp::$IS_FREELANCER])?"Да":"Нет",
'org_type'=>Org::getName(Org::getByIDCached(intval($l[Emp::$ORG]))),
'department'=>implode("\n",Emp::getDepartmentList($l)),
'staffing'=>implode("\n",Emp::getStaffingList($l)),
'isSecond'=>$isSecond,
];
if($isSecond){
$isChanged = $data[$emp_id][$year.$month]['fzp']!=$data[$emp_id][$nowYear.$nowMonth]['fzp'];
$color = ((!$isChanged)?'#1c303b':'#fb4f14');
$data[$emp_id][$nowYear.$nowMonth]['mark'] = $isChanged?"Изм":"Ок";
$data[$emp_id][$nowYear.$nowMonth]['color'] = $color;
$data[$emp_id][$nowYear.$nowMonth]['name'] = Emp::SurnameIO($l);
$data[$emp_id][$nowYear.$nowMonth]['emp_id'] = intval($l[Fot::$EMP]);
} else {
$data[$emp_id][$prevYear.$prevMonth]['mark'] = $isChanged?"Изм":"Ок";
$data[$emp_id][$prevYear.$prevMonth]['color'] = $color;
$data[$emp_id][$prevYear.$prevMonth]['name'] = Emp::SurnameIO($l);
$data[$emp_id][$prevYear.$prevMonth]['emp_id'] = intval($l[Fot::$EMP]);
}
if($isBad and $isSecond){
if(!$isBadFot){
unset($data[$emp_id]);
}
}
}
}
$res['data'] = $data;
Time::generateFilterOptions($res);
echo je($res);
}
public static function getTableData($post = [])
{
$post['options'][\ModuleTable::ROW_CLICK] = eRowClick::CUSTOM;
$post['options'][\Query::LEFT_JOINS] = [
[Emp::$table_name, Emp::$ID, Fot::$EMP],
];
$emp_id = null;
$and = [];
if(isset($post['data']['params']['id'])){
$post['options'][\Query::COUNT] = 0;
$emp_id = $post['data']['params']['id'];
$and[] = \Where::_operator(Fot::$EMP, '=', $emp_id);
$year = intval($post['options']['filter']['year'])?:date('Y');
$and[] = \Where::_operator(Fot::$YEAR, '=', $year);
$post['options'][\ModuleTable::COLUMN_LIST] = [
Fot::$YM,
Fot::$FZP,
Fot::$ADD,
Fot::$FOT,
Fot::$PK,
Fot::$PER_HOUR,
Fot::$STATUS,
];
} else {
$year = intval($post['options']['filter']['year']);
if($year) $and[] = \Where::_operator(Fot::$YEAR, '=', $year);
$month = intval($post['options']['filter']['month']);
if($month) $and[] = \Where::_operator(Fot::$MONTH, '=', $month);
if (isset($post['data']['full'])) {
$post['options'][\ModuleTable::COLUMN_LIST] = [
Fot::$EMP_NAME,
Fot::$EMP_ROLES,
Fot::$FZP,
Fot::$ADD,
Fot::$FOT,
Fot::$PER_HOUR,
Fot::$STATUS,
Fot::$EMP_DEPARTMENT,
Fot::$EMP_CITY,
Fot::$EMP_ORG,
Fot::$EMP_ORG_TYPE,
Fot::$EMP_IS_FREELANCE,
Fot::$EMP_STATUS,
];
}
}
if($and){
$post['options'][\Query::WHERE] = \Where::_and($and);
}
$post['getData'] = true;
$res = parent::getTableData($post);
$res['title'] = [
'title' => 'ФОТ',
'edit' => true,
'subtitle' => Merakomis::$FOT_TABLE_TITLE_1,
'text' => Merakomis::$FOT_TABLE_SUBTITLE_1,
'subtitle_var' => Merakomis::$_FOT_TABLE_TITLE_1,
'text_var' => Merakomis::$_FOT_TABLE_SUBTITLE_1,
];
if($emp_id){
$res['title'] = [
'title' => 'ФОТ: '.Emp::getName(Emp::getByID($emp_id)),
'edit' => true,
'subtitle' => Merakomis::$FOT_TABLE_TITLE_2,
'text' => Merakomis::$FOT_TABLE_SUBTITLE_2,
'subtitle_var' => Merakomis::$_FOT_TABLE_TITLE_2,
'text_var' => Merakomis::$_FOT_TABLE_SUBTITLE_2,
];
}
echo je($res);
}
static function cache(){
set_time_limit(0);
$p = Project::getAll();
$e = Emp::getAll();
for($y=2025;$y>=2023;$y--) {
for ($i = 1; $i <= 12; $i++) {
foreach ($p as $project) {
$pid = $project[Project::$ID];
foreach ($e as $emp){
$eid = $emp[Emp::$ID];
$time = strtotime("$y-$i-01");
$begin = date('Y-m-01',$time);
$end = date('Y-m-t',$time);
Time::getEmpsTime($begin, $end, $eid,$pid);
}
}
}
}
}
static function test2(){
$r = Fot::getEmpIdsForBudget(2025,4);
echo '<pre>';
echo var_dump($r);
echo '</pre>';
}
static function test()
{
set_time_limit(0);
for($y=2025;$y<=2025;$y++) {
$maxM = $y == 2025 ? 5 : 12;
for ($i = 1; $i <= $maxM; $i++) {
for ($j = 1; $j <= 200; $j++) {
$r = Fot::uadd([
Fot::$EMP => $j,
Fot::$YEAR => $y,
Fot::$MONTH => $i,
Fot::$FZP => rand(50000, 250000),
Fot::$ADD => rand(1000, 50000),
]);
}
}
}
}
}