Compare commits
11 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 2eb770a328 | |||
| ed1d991a84 | |||
| b454bbe77b | |||
| aa759af8c5 | |||
| fb85ac565f | |||
| 598acfd77c | |||
| e1cb68766e | |||
| bd746e18cc | |||
| 7af9eeab61 | |||
| 354aa9c3be | |||
| 2c8e32deb8 |
+2
-1
@@ -14,8 +14,9 @@ services:
|
|||||||
- internal
|
- internal
|
||||||
- myadmin
|
- myadmin
|
||||||
www:
|
www:
|
||||||
image: registry.docker.rhost.ovh/sprawozdania:0.1.8
|
image: registry.docker.rhost.ovh/sprawozdania:0.2.5
|
||||||
restart: on-failure
|
restart: on-failure
|
||||||
|
platform: linux/x86_64
|
||||||
build:
|
build:
|
||||||
context: .
|
context: .
|
||||||
dockerfile: services/www/Dockerfile
|
dockerfile: services/www/Dockerfile
|
||||||
|
|||||||
@@ -14,4 +14,7 @@ import './styles/main.less';
|
|||||||
global.jQuery = global.$ = require('jquery');
|
global.jQuery = global.$ = require('jquery');
|
||||||
require('@fortawesome/fontawesome-free/css/all.min.css');
|
require('@fortawesome/fontawesome-free/css/all.min.css');
|
||||||
require('bootstrap');
|
require('bootstrap');
|
||||||
$('[data-toggle="tooltip"]').tooltip();
|
|
||||||
|
$(function () {
|
||||||
|
$('[data-toggle="tooltip"]').tooltip()
|
||||||
|
})
|
||||||
Vendored
+2
-1
@@ -1,4 +1,5 @@
|
|||||||
import { startStimulusApp } from '@symfony/stimulus-bridge';
|
import { startStimulusApp } from '@symfony/stimulus-bridge';
|
||||||
|
import {tmp} from "./services/theme_controller";
|
||||||
|
|
||||||
// Registers Stimulus controllers from controllers.json and in the controllers/ directory
|
// Registers Stimulus controllers from controllers.json and in the controllers/ directory
|
||||||
export const app = startStimulusApp(require.context(
|
export const app = startStimulusApp(require.context(
|
||||||
@@ -6,5 +7,5 @@ export const app = startStimulusApp(require.context(
|
|||||||
true,
|
true,
|
||||||
/\.[jt]sx?$/
|
/\.[jt]sx?$/
|
||||||
));
|
));
|
||||||
|
new tmp()
|
||||||
// register any custom, 3rd party controllers here
|
// register any custom, 3rd party controllers here
|
||||||
// app.register('some_controller_name', SomeImportedController);
|
|
||||||
|
|||||||
@@ -0,0 +1,35 @@
|
|||||||
|
import { Controller } from '@hotwired/stimulus';
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This is an example Stimulus controller!
|
||||||
|
*
|
||||||
|
* Any element with a data-controller="hello" attribute will cause
|
||||||
|
* this controller to be executed. The name "hello" comes from the filename:
|
||||||
|
* hello_controller.js -> "hello"
|
||||||
|
*
|
||||||
|
* Delete this file or adapt it for your use!
|
||||||
|
*/
|
||||||
|
export default class extends Controller {
|
||||||
|
allCardsDiv;
|
||||||
|
connect() {
|
||||||
|
this.allCardsDiv = $('#allCardsReport .report-one');
|
||||||
|
}
|
||||||
|
|
||||||
|
showModal(){
|
||||||
|
const reportId = event.params.reportid, date = event.params.date;
|
||||||
|
$("#showReportModal").find('.modal-body').html(
|
||||||
|
this.findReport(reportId)
|
||||||
|
);
|
||||||
|
$("#showReportModal").find('.modal-title').html(date)
|
||||||
|
$("#showReportModal").modal('show');
|
||||||
|
}
|
||||||
|
|
||||||
|
findReport(id) {
|
||||||
|
for (const allCardsDivKey of this.allCardsDiv) {
|
||||||
|
const tmp = $(allCardsDivKey);
|
||||||
|
if (tmp.data('report_id') === id) {
|
||||||
|
return tmp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
import { Controller } from '@hotwired/stimulus';
|
||||||
|
import { tmp } from '../services/theme_controller'
|
||||||
|
|
||||||
|
export default class extends Controller {
|
||||||
|
modes;
|
||||||
|
currentState;
|
||||||
|
connect() {
|
||||||
|
this.modes = $(this.element).find('p');
|
||||||
|
this.currentState = localStorage.getItem('themeMode');
|
||||||
|
this.changeState()
|
||||||
|
var tmp1 = new tmp();
|
||||||
|
tmp1.update();
|
||||||
|
}
|
||||||
|
switch(event) {
|
||||||
|
var mode = event.params.mode;
|
||||||
|
this.changeState(mode);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
changeState(newState) {
|
||||||
|
if (typeof newState !== 'undefined') {
|
||||||
|
localStorage.setItem("themeMode", newState);
|
||||||
|
this.currentState = newState;
|
||||||
|
}
|
||||||
|
// $('html').attr('data-bs-theme', this.currentState);
|
||||||
|
this.modes.filter((e,tmp)=>{
|
||||||
|
const obj = $(tmp);
|
||||||
|
obj.toggle(!obj.hasClass(this.currentState));
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,73 @@
|
|||||||
|
export class tmp {
|
||||||
|
constructor() {
|
||||||
|
const getStoredTheme = () => localStorage.getItem('theme')
|
||||||
|
const getPreferredTheme = () => {
|
||||||
|
const storedTheme = getStoredTheme()
|
||||||
|
if (storedTheme) {
|
||||||
|
return storedTheme
|
||||||
|
}
|
||||||
|
|
||||||
|
return window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light'
|
||||||
|
}
|
||||||
|
|
||||||
|
this.setTheme(getPreferredTheme())
|
||||||
|
window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', () => {
|
||||||
|
const storedTheme = getStoredTheme()
|
||||||
|
if (storedTheme !== 'light' && storedTheme !== 'dark') {
|
||||||
|
this.setTheme(getPreferredTheme())
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
window.addEventListener('DOMContentLoaded', () => {
|
||||||
|
this.showActiveTheme(getPreferredTheme())
|
||||||
|
this.update();
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
setTheme = theme => {
|
||||||
|
if (theme === 'auto') {
|
||||||
|
document.documentElement.setAttribute('data-bs-theme', (window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light'))
|
||||||
|
} else {
|
||||||
|
document.documentElement.setAttribute('data-bs-theme', theme)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
setStoredTheme = theme => localStorage.setItem('theme', theme)
|
||||||
|
showActiveTheme = (theme, focus = false) => {
|
||||||
|
const themeSwitcher = document.querySelector('#bd-theme')
|
||||||
|
|
||||||
|
if (!themeSwitcher) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const themeSwitcherText = document.querySelector('#bd-theme-text')
|
||||||
|
const activeThemeIcon = document.querySelector('.theme-icon-active use')
|
||||||
|
const btnToActive = document.querySelector(`[data-bs-theme-value="${theme}"]`)
|
||||||
|
const svgOfActiveBtn = btnToActive.querySelector('svg use').getAttribute('href')
|
||||||
|
|
||||||
|
document.querySelectorAll('[data-bs-theme-value]').forEach(element => {
|
||||||
|
element.classList.remove('active')
|
||||||
|
element.setAttribute('aria-pressed', 'false')
|
||||||
|
})
|
||||||
|
|
||||||
|
btnToActive.classList.add('active')
|
||||||
|
btnToActive.setAttribute('aria-pressed', 'true')
|
||||||
|
activeThemeIcon.setAttribute('href', svgOfActiveBtn)
|
||||||
|
const themeSwitcherLabel = `${themeSwitcherText.textContent} (${btnToActive.dataset.bsThemeValue})`
|
||||||
|
themeSwitcher.setAttribute('aria-label', themeSwitcherLabel)
|
||||||
|
|
||||||
|
if (focus) {
|
||||||
|
themeSwitcher.focus()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
update() {
|
||||||
|
document.querySelectorAll('[data-bs-theme-value]')
|
||||||
|
.forEach(toggle => {
|
||||||
|
toggle.addEventListener('click', () => {
|
||||||
|
const theme = toggle.getAttribute('data-bs-theme-value')
|
||||||
|
this.setStoredTheme(theme)
|
||||||
|
this.setTheme(theme)
|
||||||
|
this.showActiveTheme(theme, true)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,54 +1,54 @@
|
|||||||
body {
|
body {
|
||||||
background-color: #e6e6e6;
|
//background-color: #e6e6e6;
|
||||||
}
|
}
|
||||||
.reports-all {
|
.reports-all {
|
||||||
.col {
|
.col {
|
||||||
margin-bottom: 20px;
|
margin-bottom: 20px;
|
||||||
}
|
}
|
||||||
.report-one {
|
}
|
||||||
.card-header {
|
.report-one {
|
||||||
display: flex;
|
.card-header {
|
||||||
.card-title {
|
display: flex;
|
||||||
margin: auto;
|
.card-title {
|
||||||
}
|
|
||||||
}
|
|
||||||
&.complete {
|
|
||||||
.card-header {
|
|
||||||
min-height: 52px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
margin-bottom: 10px;
|
|
||||||
.fa{
|
|
||||||
margin: auto;
|
margin: auto;
|
||||||
font-size: 20px;
|
|
||||||
padding: 5px 20px;
|
|
||||||
}
|
}
|
||||||
.btn-group {
|
}
|
||||||
width: 100%;
|
&.complete {
|
||||||
|
.card-header {
|
||||||
|
min-height: 52px;
|
||||||
}
|
}
|
||||||
.report-number {
|
}
|
||||||
position: absolute;
|
margin-bottom: 10px;
|
||||||
right: 3px;
|
.fa{
|
||||||
width: 25px;
|
margin: auto;
|
||||||
height: 25px;
|
font-size: 20px;
|
||||||
.badge {
|
padding: 5px 20px;
|
||||||
font-size: 15px;
|
}
|
||||||
}
|
.btn-group {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
.report-number {
|
||||||
|
position: absolute;
|
||||||
|
right: 3px;
|
||||||
|
width: 25px;
|
||||||
|
height: 25px;
|
||||||
|
.badge {
|
||||||
|
font-size: 15px;
|
||||||
}
|
}
|
||||||
.report-mark-uncompleted {
|
}
|
||||||
width: 25px;
|
.report-mark-uncompleted {
|
||||||
height: 25px;
|
width: 25px;
|
||||||
cursor: pointer;
|
height: 25px;
|
||||||
font-size: 12px;
|
cursor: pointer;
|
||||||
position: absolute;
|
font-size: 12px;
|
||||||
right: 2px;
|
position: absolute;
|
||||||
top:26px;
|
right: 2px;
|
||||||
.fa {
|
top:26px;
|
||||||
padding: 0;
|
.fa {
|
||||||
}
|
padding: 0;
|
||||||
.badge {
|
}
|
||||||
border: none;
|
.badge {
|
||||||
}
|
border: none;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -59,5 +59,24 @@ body {
|
|||||||
/* background-color: lightgray;*/
|
/* background-color: lightgray;*/
|
||||||
/*}*/
|
/*}*/
|
||||||
a {
|
a {
|
||||||
text-decoration: none !important;
|
//text-decoration: none !important;
|
||||||
|
}
|
||||||
|
.spinner-grow.overdue {
|
||||||
|
position: absolute;
|
||||||
|
top: 2px;
|
||||||
|
right: 2px;
|
||||||
|
}
|
||||||
|
.card-footer {
|
||||||
|
.edit-client-group {
|
||||||
|
display: inline-flex;
|
||||||
|
margin: auto;
|
||||||
|
>div {
|
||||||
|
padding: 10px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#allCardsReport{
|
||||||
|
display: none;
|
||||||
|
opacity: 0;
|
||||||
}
|
}
|
||||||
@@ -17,6 +17,7 @@
|
|||||||
"symfony/dotenv": "6.4.*",
|
"symfony/dotenv": "6.4.*",
|
||||||
"symfony/form": "6.4.*",
|
"symfony/form": "6.4.*",
|
||||||
"symfony/framework-bundle": "6.4.*",
|
"symfony/framework-bundle": "6.4.*",
|
||||||
|
"symfony/http-client": "^7.1",
|
||||||
"symfony/runtime": "6.4.*",
|
"symfony/runtime": "6.4.*",
|
||||||
"symfony/security-bundle": "6.4.*",
|
"symfony/security-bundle": "6.4.*",
|
||||||
"symfony/stimulus-bundle": "^2.18",
|
"symfony/stimulus-bundle": "^2.18",
|
||||||
|
|||||||
Generated
+645
-395
File diff suppressed because it is too large
Load Diff
@@ -10,6 +10,10 @@ framework:
|
|||||||
# Redis
|
# Redis
|
||||||
app: cache.adapter.redis
|
app: cache.adapter.redis
|
||||||
system: cache.adapter.redis
|
system: cache.adapter.redis
|
||||||
|
default_redis_provider: '%env(REDIS_URL)%'
|
||||||
|
pools:
|
||||||
|
database.cache:
|
||||||
|
adapter: cache.adapter.redis
|
||||||
|
|
||||||
# APCu (not recommended with heavy random-write workloads as memory fragmentation can cause perf issues)
|
# APCu (not recommended with heavy random-write workloads as memory fragmentation can cause perf issues)
|
||||||
#app: cache.adapter.apcu
|
#app: cache.adapter.apcu
|
||||||
|
|||||||
@@ -15,6 +15,24 @@ doctrine:
|
|||||||
validate_xml_mapping: true
|
validate_xml_mapping: true
|
||||||
naming_strategy: doctrine.orm.naming_strategy.underscore_number_aware
|
naming_strategy: doctrine.orm.naming_strategy.underscore_number_aware
|
||||||
auto_mapping: true
|
auto_mapping: true
|
||||||
|
second_level_cache:
|
||||||
|
enabled: true
|
||||||
|
regions:
|
||||||
|
user_cache:
|
||||||
|
lifetime: 8640000
|
||||||
|
cache_driver: { type: service, id: database.cache }
|
||||||
|
schedule_cache:
|
||||||
|
lifetime: 864000
|
||||||
|
cache_driver: { type: service, id: database.cache }
|
||||||
|
report_cache:
|
||||||
|
lifetime: 864000
|
||||||
|
cache_driver: { type: service, id: database.cache }
|
||||||
|
client_cache:
|
||||||
|
lifetime: 864000
|
||||||
|
cache_driver: { type: service, id: database.cache }
|
||||||
|
default_cache:
|
||||||
|
lifetime: 864000
|
||||||
|
cache_driver: { type: service, id: database.cache }
|
||||||
mappings:
|
mappings:
|
||||||
App:
|
App:
|
||||||
type: attribute
|
type: attribute
|
||||||
|
|||||||
@@ -0,0 +1,3 @@
|
|||||||
|
<?php // dev.API_FAKTUROWNIA.f73a67 on Fri, 01 Nov 2024 22:52:28 +0100
|
||||||
|
|
||||||
|
return "\xA9c\xD0\xC5\xD1\x3Aek\xE6\x24\x16\x15b\x3A\xDF\x83\x9B\xED\xE8n\x04_d\x5B\xAE8\x1B\xAC\x02\x2C\x9CA\xFB\x8Ee\x99\xFC3\xDE\xC34f\x28\x08\x26\xC8\x26o\x88\xF9\xF4z";
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
return [
|
return [
|
||||||
|
'API_FAKTUROWNIA' => null,
|
||||||
'DATABASE_PASSWORD' => null,
|
'DATABASE_PASSWORD' => null,
|
||||||
];
|
];
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
<?php // prod.DATABASE_PASSWORD.b77cc3 on Thu, 25 Jul 2024 14:54:39 +0200
|
<?php // prod.DATABASE_PASSWORD.b77cc3 on Wed, 21 Aug 2024 11:10:09 +0200
|
||||||
|
|
||||||
return "\x0FA\x82\x24\x0E\xC5I\x1Ep7\xA5A\x1Cx\x80\x18m\xB0\x17\x1B\x82B\x92\x99\xAF\x9APi\x24\x9B\x009\x15\xA4\x25k\xBE\x20\xE8t\xF9\xD1\xF9W\xD3\xC4\x25\xFFU\x7D\xAF\x04\xE9\xF9j\x7F\xFBFZ\x81\x0A\x254\x12";
|
return "u\x2C\x1D\xF4\x2CKm\x98\xCA\x01\x7C\xABJ\x3A\xA7\xCA\x1B\x94R\x98\xF5D\xC9\x25\xCDY\xDF\x5C\x23\x8DLK\xBD\x03jew\x5C9\x7B\x7F\x05\x5EE\x21Z\x9A\xB0\x87\xC9\xB8\xCES\xB7N\xE6\xFF\xA4\xB6\xDA\xFC\xC8\xB3\x94";
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
# Put parameters here that don't need to change on each machine where the app is deployed
|
# Put parameters here that don't need to change on each machine where the app is deployed
|
||||||
# https://symfony.com/doc/current/best_practices.html#use-parameters-for-application-configuration
|
# https://symfony.com/doc/current/best_practices.html#use-parameters-for-application-configuration
|
||||||
parameters:
|
parameters:
|
||||||
|
FAKTUROWNIA_API: '%env(API_FAKTUROWNIA)%'
|
||||||
|
|
||||||
services:
|
services:
|
||||||
# default configuration for services in *this* file
|
# default configuration for services in *this* file
|
||||||
@@ -24,5 +25,6 @@ services:
|
|||||||
resource: '../src/Services/'
|
resource: '../src/Services/'
|
||||||
arguments:
|
arguments:
|
||||||
- '@doctrine.orm.entity_manager'
|
- '@doctrine.orm.entity_manager'
|
||||||
|
- '@Symfony\Contracts\HttpClient\HttpClientInterface'
|
||||||
# add more service definitions when explicit configuration is needed
|
# add more service definitions when explicit configuration is needed
|
||||||
# please note that last definitions always *replace* previous ones
|
# please note that last definitions always *replace* previous ones
|
||||||
|
|||||||
@@ -0,0 +1,31 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace DoctrineMigrations;
|
||||||
|
|
||||||
|
use Doctrine\DBAL\Schema\Schema;
|
||||||
|
use Doctrine\Migrations\AbstractMigration;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Auto-generated Migration: Please modify to your needs!
|
||||||
|
*/
|
||||||
|
final class Version20250329215035 extends AbstractMigration
|
||||||
|
{
|
||||||
|
public function getDescription(): string
|
||||||
|
{
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
public function up(Schema $schema): void
|
||||||
|
{
|
||||||
|
// this up() migration is auto-generated, please modify it to your needs
|
||||||
|
$this->addSql('ALTER TABLE reports ADD highlight INT DEFAULT 0 NOT NULL');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function down(Schema $schema): void
|
||||||
|
{
|
||||||
|
// this down() migration is auto-generated, please modify it to your needs
|
||||||
|
$this->addSql('ALTER TABLE reports DROP highlight');
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace DoctrineMigrations;
|
||||||
|
|
||||||
|
use Doctrine\DBAL\Schema\Schema;
|
||||||
|
use Doctrine\Migrations\AbstractMigration;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Auto-generated Migration: Please modify to your needs!
|
||||||
|
*/
|
||||||
|
final class Version20250330100207 extends AbstractMigration
|
||||||
|
{
|
||||||
|
public function getDescription(): string
|
||||||
|
{
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
public function up(Schema $schema): void
|
||||||
|
{
|
||||||
|
// this up() migration is auto-generated, please modify it to your needs
|
||||||
|
$this->addSql('ALTER TABLE clients ADD highlight INT DEFAULT 0 NOT NULL');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function down(Schema $schema): void
|
||||||
|
{
|
||||||
|
// this down() migration is auto-generated, please modify it to your needs
|
||||||
|
$this->addSql('ALTER TABLE clients DROP highlight');
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -8,7 +8,9 @@ use App\Entity\ReportsTodo;
|
|||||||
use App\Enum\Months;
|
use App\Enum\Months;
|
||||||
use App\Enum\ReportStatus;
|
use App\Enum\ReportStatus;
|
||||||
use App\Enum\ReportTodoEnum;
|
use App\Enum\ReportTodoEnum;
|
||||||
|
use App\Enum\ReportHighlight;
|
||||||
use App\Helper\MonthHelper;
|
use App\Helper\MonthHelper;
|
||||||
|
use App\Services\OverdueReports;
|
||||||
use Doctrine\ORM\EntityManagerInterface;
|
use Doctrine\ORM\EntityManagerInterface;
|
||||||
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
|
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
|
||||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||||
@@ -23,33 +25,39 @@ use Symfony\Component\HttpFoundation\Request;
|
|||||||
use Symfony\Component\HttpFoundation\Response;
|
use Symfony\Component\HttpFoundation\Response;
|
||||||
use Symfony\Component\Routing\Attribute\Route;
|
use Symfony\Component\Routing\Attribute\Route;
|
||||||
use Symfony\Component\Security\Http\Attribute\IsGranted;
|
use Symfony\Component\Security\Http\Attribute\IsGranted;
|
||||||
|
use Symfony\Contracts\Cache\CacheInterface;
|
||||||
|
|
||||||
class BaseController extends AbstractController
|
class BaseController extends AbstractController
|
||||||
{
|
{
|
||||||
private MonthHelper $monthHelper;
|
|
||||||
|
|
||||||
public function __construct(){
|
|
||||||
$this->monthHelper = new MonthHelper();
|
|
||||||
}
|
|
||||||
|
|
||||||
#[Route('/', name: 'index')]
|
#[Route('/', name: 'index')]
|
||||||
public function index(): Response
|
public function index(): Response
|
||||||
{
|
{
|
||||||
if (!$this->isGranted('reportView')) {
|
if ($this->isGranted('reportView')) {
|
||||||
|
return $this->redirectToRoute('app_base');
|
||||||
|
}
|
||||||
|
if ($this->isGranted('scheduleView')) {
|
||||||
return $this->redirectToRoute('app_schedule');
|
return $this->redirectToRoute('app_schedule');
|
||||||
}
|
}
|
||||||
|
if ($this->isGranted('clientView')) {
|
||||||
|
return $this->redirectToRoute('app_customers_list');
|
||||||
|
}
|
||||||
return $this->redirectToRoute('app_base');
|
return $this->redirectToRoute('app_base');
|
||||||
}
|
}
|
||||||
#[Route('/reports/{monthId}', name: 'app_base')]
|
#[Route('/reports/{monthId}/{clientId}', name: 'app_base')]
|
||||||
#[IsGranted('reportView')]
|
#[IsGranted('reportView')]
|
||||||
public function reportsIndex(EntityManagerInterface $entityManager, int $monthId = 0) : Response
|
public function reportsIndex(EntityManagerInterface $entityManager, CacheInterface $cache, OverdueReports $overdueReports, int $monthId = 0, int $clientId = 0) : Response
|
||||||
{
|
{
|
||||||
|
$client = null;
|
||||||
|
if ($clientId) {
|
||||||
|
$client = $entityManager->getRepository(Clients::class)->find($clientId);
|
||||||
|
}
|
||||||
|
$overdueReports->setClient($client);
|
||||||
|
$monthHelper = new MonthHelper($overdueReports);
|
||||||
$isOverdue = false;
|
$isOverdue = false;
|
||||||
if ($monthId > -1) {
|
$monthCurrentDate = $monthHelper->getCurrentMonthDate($monthId);
|
||||||
$monthCurrent = $this->monthHelper->getCurrentMonth($monthId);
|
$reportsAll = $this->takeReportsAll($entityManager, $clientId, $monthCurrentDate);
|
||||||
$reportsAll = $entityManager->getRepository(Reports::class)->findAllInMonth($monthCurrent);
|
|
||||||
} else {
|
if ($monthId < 0) {
|
||||||
$reportsAll = $entityManager->getRepository(Reports::class)->findAllOverdue();
|
|
||||||
$isOverdue = true;
|
$isOverdue = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -67,10 +75,25 @@ class BaseController extends AbstractController
|
|||||||
ksort($reports);
|
ksort($reports);
|
||||||
return $this->render('reports/list.html.twig', [
|
return $this->render('reports/list.html.twig', [
|
||||||
'reportsGroup' => $reports,
|
'reportsGroup' => $reports,
|
||||||
'months' => $this->monthHelper->takeMonths(),
|
'months' => $monthHelper->takeMonths(),
|
||||||
'currentMonth' => $monthCurrent ?? null,
|
'currentMonth' => $monthCurrentDate ?? null,
|
||||||
'reportToDoList' => ReportTodoEnum::cases(),
|
'reportToDoList' => ReportTodoEnum::cases(),
|
||||||
'isOverdue' => $isOverdue,
|
'isOverdue' => $isOverdue,
|
||||||
|
'countOverdueLeft' => $overdueReports->getLeftCount(),
|
||||||
|
'client' => $client,
|
||||||
|
'clientId' => $clientId,
|
||||||
|
'highlightStatus' => ReportHighlight::cases()
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function takeReportsAll(EntityManagerInterface $entityManager, int $clientId, ?\DateTime $monthCurrent = null) : array
|
||||||
|
{
|
||||||
|
if ($monthCurrent !== null) {
|
||||||
|
$ret = $entityManager->getRepository(Reports::class)->findAllInMonth($monthCurrent,$clientId);
|
||||||
|
} else {
|
||||||
|
$ret = $entityManager->getRepository(Reports::class)->findAllOverdue($clientId);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $ret;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,6 +6,9 @@ use App\Entity\Clients;
|
|||||||
use App\Entity\Notes;
|
use App\Entity\Notes;
|
||||||
use App\Entity\Reports;
|
use App\Entity\Reports;
|
||||||
use App\Entity\Schedule;
|
use App\Entity\Schedule;
|
||||||
|
use App\Enum\ReportHighlight;
|
||||||
|
use App\Enum\ReportStatus;
|
||||||
|
use App\Enum\ReportTodoEnum;
|
||||||
use App\Services\AddReports;
|
use App\Services\AddReports;
|
||||||
use Doctrine\ORM\EntityManagerInterface;
|
use Doctrine\ORM\EntityManagerInterface;
|
||||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||||
@@ -50,13 +53,15 @@ class ClientController extends AbstractController
|
|||||||
$schedules = $entityManager->getRepository(Schedule::class)->findOneBy(["client" => $clients->getId()]);
|
$schedules = $entityManager->getRepository(Schedule::class)->findOneBy(["client" => $clients->getId()]);
|
||||||
$reports = $entityManager->getRepository(Reports::class)->findBy(["client" => $clients->getId()],["number"=>"DESC"]);
|
$reports = $entityManager->getRepository(Reports::class)->findBy(["client" => $clients->getId()],["number"=>"DESC"]);
|
||||||
$notes = $entityManager->getRepository(Notes::class)->findOneBy(["clientId" => $clients->getId()]);
|
$notes = $entityManager->getRepository(Notes::class)->findOneBy(["clientId" => $clients->getId()]);
|
||||||
|
|
||||||
return $this->render('customers/show.html.twig', [
|
return $this->render('customers/show.html.twig', [
|
||||||
'client' => $clients,
|
'client' => $clients,
|
||||||
'schedules' => $schedules,
|
'schedules' => $schedules,
|
||||||
'reports' => $reports,
|
'reports' => $reports,
|
||||||
'notes' => $notes,
|
'notes' => $notes,
|
||||||
'backUrl' => $request->headers->get('referer')
|
'backUrl' => $request->headers->get('referer'),
|
||||||
|
'reportToDoList' => ReportTodoEnum::cases(),
|
||||||
|
'reportStatus' => ReportStatus::INSERT,
|
||||||
|
'highlightStatus' => ReportHighlight::cases()
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
#[Route('/dodaj_klienta/{id}', name: 'app_add_client', defaults: ['id'=>0])]
|
#[Route('/dodaj_klienta/{id}', name: 'app_add_client', defaults: ['id'=>0])]
|
||||||
@@ -76,6 +81,7 @@ class ClientController extends AbstractController
|
|||||||
$newClient = $form->getData();
|
$newClient = $form->getData();
|
||||||
$entityManager->persist($newClient);
|
$entityManager->persist($newClient);
|
||||||
$entityManager->flush();
|
$entityManager->flush();
|
||||||
|
$entityManager->getCache()->evictEntityRegion(Clients::class);
|
||||||
if (!$isEdit) {
|
if (!$isEdit) {
|
||||||
$addReports->setClient($newClient);
|
$addReports->setClient($newClient);
|
||||||
$addReports->init();
|
$addReports->init();
|
||||||
@@ -161,4 +167,18 @@ class ClientController extends AbstractController
|
|||||||
->add('submitAndRedirect', SubmitType::class, )
|
->add('submitAndRedirect', SubmitType::class, )
|
||||||
->getForm();
|
->getForm();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[Route('/client_highlight/{id}', name: 'app_client_highlight', methods: ['POST'])]
|
||||||
|
public function updateHighlight(EntityManagerInterface $entityManager, Request $request, Clients $client): Response
|
||||||
|
{
|
||||||
|
$token = $request->get("token");
|
||||||
|
if ($this->isCsrfTokenValid('client-highlight', $token)) {
|
||||||
|
$highlightId = intval($request->get("highlight_id"));
|
||||||
|
$highlight = ReportHighlight::tryFrom($highlightId);
|
||||||
|
$client->setHighlight($highlight);
|
||||||
|
$entityManager->persist($client);
|
||||||
|
$entityManager->flush();
|
||||||
|
}
|
||||||
|
return $this->redirectToRoute('app_client', ['id'=>$client->getId()]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -4,8 +4,11 @@ namespace App\Controller;
|
|||||||
use App\Entity\Clients;
|
use App\Entity\Clients;
|
||||||
use App\Entity\Reports;
|
use App\Entity\Reports;
|
||||||
use App\Entity\ReportsTodo;
|
use App\Entity\ReportsTodo;
|
||||||
|
use App\Entity\Schedule;
|
||||||
use App\Enum\ReportTodoEnum;
|
use App\Enum\ReportTodoEnum;
|
||||||
|
use App\Enum\ReportHighlight;
|
||||||
use App\Services\AddReports;
|
use App\Services\AddReports;
|
||||||
|
use App\Services\InvoiceServices;
|
||||||
use Doctrine\ORM\EntityManagerInterface;
|
use Doctrine\ORM\EntityManagerInterface;
|
||||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||||
use Symfony\Component\HttpFoundation\Request;
|
use Symfony\Component\HttpFoundation\Request;
|
||||||
@@ -17,12 +20,11 @@ class ReportsController extends AbstractController
|
|||||||
{
|
{
|
||||||
#[Route('/set-status-todo/{id}', name: 'app_set_status_todo', methods: ['POST'])]
|
#[Route('/set-status-todo/{id}', name: 'app_set_status_todo', methods: ['POST'])]
|
||||||
#[IsGranted('reportEdit')]
|
#[IsGranted('reportEdit')]
|
||||||
public function setStatusTodo(EntityManagerInterface $entityManager, AddReports $reportsService, Request $request, Reports $report): Response
|
public function setStatusTodo(EntityManagerInterface $entityManager, AddReports $reportsService, InvoiceServices $invoiceServices, Request $request, Reports $report): Response
|
||||||
{
|
{
|
||||||
$token = $request->get("token");
|
$token = $request->get("token");
|
||||||
if ($this->isCsrfTokenValid('report-status', $token)) {
|
if ($this->isCsrfTokenValid('report-status', $token)) {
|
||||||
$reportsService->setClient($report->getClient());
|
$reportsService->setClient($report->getClient());
|
||||||
$isDone = false;
|
|
||||||
if ($request->get("unDone")){
|
if ($request->get("unDone")){
|
||||||
$todo = $entityManager->getRepository(ReportsTodo::class)->findOneBy([
|
$todo = $entityManager->getRepository(ReportsTodo::class)->findOneBy([
|
||||||
"report" => $report->getId(),
|
"report" => $report->getId(),
|
||||||
@@ -30,8 +32,12 @@ class ReportsController extends AbstractController
|
|||||||
]);
|
]);
|
||||||
$todo->setDeleted(true);
|
$todo->setDeleted(true);
|
||||||
$entityManager->persist($todo);
|
$entityManager->persist($todo);
|
||||||
|
$report->setDone(false);
|
||||||
} else {
|
} else {
|
||||||
foreach (ReportTodoEnum::cases() as $case) {
|
foreach (ReportTodoEnum::cases() as $case) {
|
||||||
|
if (!$request->get($case->value)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
$todo = $entityManager->getRepository(ReportsTodo::class)->findOneBy([
|
$todo = $entityManager->getRepository(ReportsTodo::class)->findOneBy([
|
||||||
"report" => $report->getId(),
|
"report" => $report->getId(),
|
||||||
"name" => $case->value
|
"name" => $case->value
|
||||||
@@ -40,21 +46,29 @@ class ReportsController extends AbstractController
|
|||||||
$todo = new ReportsTodo();
|
$todo = new ReportsTodo();
|
||||||
$todo->setReport($report);
|
$todo->setReport($report);
|
||||||
$todo->setName($case);
|
$todo->setName($case);
|
||||||
}
|
|
||||||
if ($request->get($case->value) !== null) {
|
|
||||||
$todo->setDeleted(false);
|
|
||||||
} else {
|
} else {
|
||||||
$todo->setDeleted(true);
|
$todo->setDeleted(!$todo->isDeleted());
|
||||||
}
|
}
|
||||||
if ($todo->getName() === ReportTodoEnum::COMPLETE && !$todo->isDeleted()) {
|
if ($todo->getName() === ReportTodoEnum::COMPLETE) {
|
||||||
$isDone = true;
|
if ($todo->isDeleted()) {
|
||||||
|
$report->setDone(false);
|
||||||
|
} else {
|
||||||
|
$report->setDone(true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
// if ($todo->getName() === ReportTodoEnum::INVOICE_SEND && !$todo->isDeleted()) {
|
||||||
|
// $invoiceServices->setApiKey($this->getParameter('FAKTUROWNIA_API'));
|
||||||
|
// $invoiceServices->setClients($report->getClient());
|
||||||
|
// $invoiceServices->setReportDate($report->getDateStart());
|
||||||
|
// $invoiceServices->send();
|
||||||
|
// }
|
||||||
$entityManager->persist($todo);
|
$entityManager->persist($todo);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
$report->setDone($isDone);
|
|
||||||
$entityManager->persist($report);
|
$entityManager->persist($report);
|
||||||
$entityManager->flush();
|
$entityManager->flush();
|
||||||
|
$entityManager->getCache()->evictCollection(Reports::class,"reportsTodos",$report->getId());
|
||||||
$reportsService->tryAddNextReport();
|
$reportsService->tryAddNextReport();
|
||||||
}
|
}
|
||||||
return $this->redirect($request->headers->get('referer'));
|
return $this->redirect($request->headers->get('referer'));
|
||||||
@@ -96,4 +110,24 @@ class ReportsController extends AbstractController
|
|||||||
}
|
}
|
||||||
return $this->redirectToRoute('app_client', ['id'=>$clientId]);
|
return $this->redirectToRoute('app_client', ['id'=>$clientId]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[Route('/testapi')]
|
||||||
|
public function test()
|
||||||
|
{
|
||||||
|
return new Response(var_export($_POST,true));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[Route('/reports_highlight/{id}', name: 'app_report_highlight', methods: ['POST'])]
|
||||||
|
public function updateHighlight(EntityManagerInterface $entityManager, Request $request, Reports $reports): Response
|
||||||
|
{
|
||||||
|
$token = $request->get("token");
|
||||||
|
if ($this->isCsrfTokenValid('schedule-highlight', $token)) {
|
||||||
|
$highlightId = intval($request->get("highlight_id"));
|
||||||
|
$highlight = ReportHighlight::tryFrom($highlightId);
|
||||||
|
$reports->setHighlight($highlight);
|
||||||
|
$entityManager->persist($reports);
|
||||||
|
$entityManager->flush();
|
||||||
|
}
|
||||||
|
return $this->redirect($request->headers->get('referer') ?? $this->generateUrl('app_schedule'));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -10,14 +10,17 @@ use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
|||||||
use Symfony\Component\HttpFoundation\Request;
|
use Symfony\Component\HttpFoundation\Request;
|
||||||
use Symfony\Component\HttpFoundation\Response;
|
use Symfony\Component\HttpFoundation\Response;
|
||||||
use Symfony\Component\Routing\Attribute\Route;
|
use Symfony\Component\Routing\Attribute\Route;
|
||||||
|
use Symfony\Component\Security\Http\Attribute\IsGranted;
|
||||||
|
|
||||||
class ScheduleController extends AbstractController
|
class ScheduleController extends AbstractController
|
||||||
{
|
{
|
||||||
#[Route('/schedule/{typeId}', name: 'app_schedule', defaults: ['typeId' => 1])]
|
#[Route('/schedule/{typeId}', name: 'app_schedule', defaults: ['typeId' => 1])]
|
||||||
|
#[IsGranted('scheduleView')]
|
||||||
public function index(EntityManagerInterface $entityManager, int $typeId = 1): Response
|
public function index(EntityManagerInterface $entityManager, int $typeId = 1): Response
|
||||||
{
|
{
|
||||||
if ($typeId == 1) {
|
if ($typeId == 1) {
|
||||||
$schedulesTmp = $entityManager->getRepository(Schedule::class)->findAllCurrent();
|
$schedulesTmp = $entityManager->getRepository(Schedule::class)->findAllCurrent();
|
||||||
|
$isOverdue = $entityManager->getRepository(Schedule::class)->findAllOverdue(true);
|
||||||
} else {
|
} else {
|
||||||
$schedulesTmp = $entityManager->getRepository(Schedule::class)->findAllOverdue();
|
$schedulesTmp = $entityManager->getRepository(Schedule::class)->findAllOverdue();
|
||||||
}
|
}
|
||||||
@@ -25,16 +28,16 @@ class ScheduleController extends AbstractController
|
|||||||
return $this->render('schedule/index.html.twig', [
|
return $this->render('schedule/index.html.twig', [
|
||||||
'typeId' => $typeId,
|
'typeId' => $typeId,
|
||||||
'schedules' => $schedulesTmp,
|
'schedules' => $schedulesTmp,
|
||||||
|
'isOverdue' => $isOverdue ?? false,
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[Route('/schedule_status', name: 'app_schedule_status')]
|
#[Route('/schedule_status/{id}', name: 'app_schedule_status', methods: ['POST'])]
|
||||||
public function setDone(EntityManagerInterface $entityManager, Request $request): Response
|
#[IsGranted('scheduleEdit')]
|
||||||
|
public function setDone(EntityManagerInterface $entityManager, Request $request, Schedule $schedule): Response
|
||||||
{
|
{
|
||||||
$scheduleId = $request->getPayload()->get('scheduleId');
|
$token = $request->get("token");
|
||||||
$token = $request->getPayload()->get("token");
|
if ($this->isCsrfTokenValid('schedule-status', $token)) {
|
||||||
if ($scheduleId && $this->isCsrfTokenValid('schedule-status', $token)) {
|
|
||||||
$schedule = $entityManager->getRepository(Schedule::class)->find($scheduleId);
|
|
||||||
$isDone = true;
|
$isDone = true;
|
||||||
if ($schedule->isDone()) {
|
if ($schedule->isDone()) {
|
||||||
$isDone = false;
|
$isDone = false;
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
namespace App\Entity;
|
namespace App\Entity;
|
||||||
|
|
||||||
|
use App\Enum\ReportHighlight;
|
||||||
use App\Repository\ClientsRepository;
|
use App\Repository\ClientsRepository;
|
||||||
use Doctrine\Common\Collections\ArrayCollection;
|
use Doctrine\Common\Collections\ArrayCollection;
|
||||||
use Doctrine\Common\Collections\Collection;
|
use Doctrine\Common\Collections\Collection;
|
||||||
@@ -9,6 +10,7 @@ use Doctrine\DBAL\Types\Types;
|
|||||||
use Doctrine\ORM\Mapping as ORM;
|
use Doctrine\ORM\Mapping as ORM;
|
||||||
|
|
||||||
#[ORM\Entity(repositoryClass: ClientsRepository::class)]
|
#[ORM\Entity(repositoryClass: ClientsRepository::class)]
|
||||||
|
#[ORM\Cache(usage: 'NONSTRICT_READ_WRITE', region: 'client_cache')]
|
||||||
class Clients
|
class Clients
|
||||||
{
|
{
|
||||||
#[ORM\Id]
|
#[ORM\Id]
|
||||||
@@ -49,6 +51,9 @@ class Clients
|
|||||||
#[ORM\Column(nullable: true)]
|
#[ORM\Column(nullable: true)]
|
||||||
private ?int $intPhone = null;
|
private ?int $intPhone = null;
|
||||||
|
|
||||||
|
#[ORM\Column(enumType: ReportHighlight::class, options: ["default" => "0"])]
|
||||||
|
private ReportHighlight $highlight = ReportHighlight::STANDARD;
|
||||||
|
|
||||||
public function __construct()
|
public function __construct()
|
||||||
{
|
{
|
||||||
$this->schedules = new ArrayCollection();
|
$this->schedules = new ArrayCollection();
|
||||||
@@ -197,4 +202,16 @@ class Clients
|
|||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getHighlight(): ReportHighlight
|
||||||
|
{
|
||||||
|
return $this->highlight;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setHighlight(ReportHighlight $highlight): static
|
||||||
|
{
|
||||||
|
$this->highlight = $highlight;
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ use Doctrine\DBAL\Types\Types;
|
|||||||
use Doctrine\ORM\Mapping as ORM;
|
use Doctrine\ORM\Mapping as ORM;
|
||||||
|
|
||||||
#[ORM\Entity(repositoryClass: NotesRepository::class)]
|
#[ORM\Entity(repositoryClass: NotesRepository::class)]
|
||||||
|
#[ORM\Cache(usage: 'NONSTRICT_READ_WRITE', region: 'default_cache')]
|
||||||
class Notes
|
class Notes
|
||||||
{
|
{
|
||||||
#[ORM\Id]
|
#[ORM\Id]
|
||||||
|
|||||||
@@ -2,15 +2,21 @@
|
|||||||
|
|
||||||
namespace App\Entity;
|
namespace App\Entity;
|
||||||
|
|
||||||
|
use App\Enum\ReportHighlight;
|
||||||
use App\Enum\ReportStatus;
|
use App\Enum\ReportStatus;
|
||||||
use App\Enum\ReportTodoEnum;
|
use App\Enum\ReportTodoEnum;
|
||||||
|
use App\Helper\MonthHelper;
|
||||||
use App\Repository\ReportsRepository;
|
use App\Repository\ReportsRepository;
|
||||||
|
use App\Services\AddReports;
|
||||||
|
use App\Services\MailtoServices;
|
||||||
use Doctrine\Common\Collections\ArrayCollection;
|
use Doctrine\Common\Collections\ArrayCollection;
|
||||||
use Doctrine\Common\Collections\Collection;
|
use Doctrine\Common\Collections\Collection;
|
||||||
use Doctrine\DBAL\Types\Types;
|
use Doctrine\DBAL\Types\Types;
|
||||||
use Doctrine\ORM\Mapping as ORM;
|
use Doctrine\ORM\Mapping as ORM;
|
||||||
|
|
||||||
#[ORM\Entity(repositoryClass: ReportsRepository::class)]
|
#[ORM\Entity(repositoryClass: ReportsRepository::class)]
|
||||||
|
#[ORM\Cache(usage: 'NONSTRICT_READ_WRITE', region: 'report_cache')]
|
||||||
|
|
||||||
class Reports
|
class Reports
|
||||||
{
|
{
|
||||||
#[ORM\Id]
|
#[ORM\Id]
|
||||||
@@ -29,6 +35,7 @@ class Reports
|
|||||||
* @var Collection<int, ReportsTodo>
|
* @var Collection<int, ReportsTodo>
|
||||||
*/
|
*/
|
||||||
#[ORM\OneToMany(targetEntity: ReportsTodo::class, mappedBy: 'report', orphanRemoval: true)]
|
#[ORM\OneToMany(targetEntity: ReportsTodo::class, mappedBy: 'report', orphanRemoval: true)]
|
||||||
|
#[ORM\Cache(usage: 'READ_ONLY', region: 'report_cache')]
|
||||||
|
|
||||||
private Collection $reportsTodos;
|
private Collection $reportsTodos;
|
||||||
|
|
||||||
@@ -43,6 +50,9 @@ class Reports
|
|||||||
#[ORM\Column]
|
#[ORM\Column]
|
||||||
private ?int $number = null;
|
private ?int $number = null;
|
||||||
|
|
||||||
|
#[ORM\Column(enumType: ReportHighlight::class, options: ["default" => "0"])]
|
||||||
|
private ReportHighlight $highlight = ReportHighlight::STANDARD;
|
||||||
|
|
||||||
public function __construct()
|
public function __construct()
|
||||||
{
|
{
|
||||||
$this->reportsTodos = new ArrayCollection();
|
$this->reportsTodos = new ArrayCollection();
|
||||||
@@ -124,6 +134,11 @@ class Reports
|
|||||||
return $this->isReportsTodo(ReportTodoEnum::COMPLETE);
|
return $this->isReportsTodo(ReportTodoEnum::COMPLETE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function isEmailSend(): bool
|
||||||
|
{
|
||||||
|
return $this->isReportsTodo(ReportTodoEnum::SENT_EMAIL);
|
||||||
|
}
|
||||||
|
|
||||||
public function countTodoReports(): int
|
public function countTodoReports(): int
|
||||||
{
|
{
|
||||||
$count = 0;
|
$count = 0;
|
||||||
@@ -194,4 +209,23 @@ class Reports
|
|||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function takeMailToUrl(): string
|
||||||
|
{
|
||||||
|
$service = new MailtoServices();
|
||||||
|
|
||||||
|
return $service->takeUrl($this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getHighlight(): ReportHighlight
|
||||||
|
{
|
||||||
|
return $this->highlight;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setHighlight(ReportHighlight $highlight): static
|
||||||
|
{
|
||||||
|
$this->highlight = $highlight;
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ use Doctrine\DBAL\Types\Types;
|
|||||||
use Doctrine\ORM\Mapping as ORM;
|
use Doctrine\ORM\Mapping as ORM;
|
||||||
|
|
||||||
#[ORM\Entity(repositoryClass: ReportsTodoRepository::class)]
|
#[ORM\Entity(repositoryClass: ReportsTodoRepository::class)]
|
||||||
|
#[ORM\Cache(usage: 'NONSTRICT_READ_WRITE', region: 'report_cache')]
|
||||||
class ReportsTodo
|
class ReportsTodo
|
||||||
{
|
{
|
||||||
#[ORM\Id]
|
#[ORM\Id]
|
||||||
@@ -19,7 +20,7 @@ class ReportsTodo
|
|||||||
#[ORM\Column(type: Types::SMALLINT, enumType: ReportTodoEnum::class)]
|
#[ORM\Column(type: Types::SMALLINT, enumType: ReportTodoEnum::class)]
|
||||||
private ?ReportTodoEnum $name = null;
|
private ?ReportTodoEnum $name = null;
|
||||||
|
|
||||||
#[ORM\ManyToOne]
|
#[ORM\ManyToOne(inversedBy: 'reportsTodos')]
|
||||||
#[ORM\JoinColumn(referencedColumnName: 'id', nullable: false)]
|
#[ORM\JoinColumn(referencedColumnName: 'id', nullable: false)]
|
||||||
private ?Reports $report = null;
|
private ?Reports $report = null;
|
||||||
|
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ use Doctrine\DBAL\Types\Types;
|
|||||||
use Doctrine\ORM\Mapping as ORM;
|
use Doctrine\ORM\Mapping as ORM;
|
||||||
|
|
||||||
#[ORM\Entity(repositoryClass: ScheduleRepository::class)]
|
#[ORM\Entity(repositoryClass: ScheduleRepository::class)]
|
||||||
|
#[ORM\Cache(usage: 'NONSTRICT_READ_WRITE', region: 'schedule_cache')]
|
||||||
class Schedule
|
class Schedule
|
||||||
{
|
{
|
||||||
#[ORM\Id]
|
#[ORM\Id]
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ use Symfony\Component\Security\Core\User\UserInterface;
|
|||||||
|
|
||||||
#[ORM\Entity(repositoryClass: UserRepository::class)]
|
#[ORM\Entity(repositoryClass: UserRepository::class)]
|
||||||
#[ORM\UniqueConstraint(name: 'UNIQ_IDENTIFIER_USERNAME', fields: ['username'])]
|
#[ORM\UniqueConstraint(name: 'UNIQ_IDENTIFIER_USERNAME', fields: ['username'])]
|
||||||
|
#[ORM\Cache(usage: 'READ_ONLY', region: 'user_cache')]
|
||||||
class User implements UserInterface, PasswordAuthenticatedUserInterface
|
class User implements UserInterface, PasswordAuthenticatedUserInterface
|
||||||
{
|
{
|
||||||
#[ORM\Id]
|
#[ORM\Id]
|
||||||
|
|||||||
@@ -0,0 +1,32 @@
|
|||||||
|
<?php
|
||||||
|
namespace App\Enum;
|
||||||
|
|
||||||
|
enum ReportHighlight: int
|
||||||
|
{
|
||||||
|
case STANDARD = 0;
|
||||||
|
case INFO = 1;
|
||||||
|
case WARNING = 5;
|
||||||
|
case DANGER = 10;
|
||||||
|
|
||||||
|
|
||||||
|
public function borderColor(): string
|
||||||
|
{
|
||||||
|
return match ($this)
|
||||||
|
{
|
||||||
|
ReportHighlight::STANDARD => '',
|
||||||
|
ReportHighlight::WARNING => 'warning',
|
||||||
|
ReportHighlight::INFO => 'info',
|
||||||
|
ReportHighlight::DANGER => 'danger',
|
||||||
|
};
|
||||||
|
}
|
||||||
|
public function buttonLang(): string
|
||||||
|
{
|
||||||
|
return match ($this)
|
||||||
|
{
|
||||||
|
ReportHighlight::STANDARD => 'Brak',
|
||||||
|
ReportHighlight::WARNING => 'Ostrzeżenie',
|
||||||
|
ReportHighlight::INFO => 'Informacja',
|
||||||
|
ReportHighlight::DANGER => 'Ważne',
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -18,4 +18,15 @@ enum ScheduleStatus: int
|
|||||||
ScheduleStatus::COMPLETED => 'success',
|
ScheduleStatus::COMPLETED => 'success',
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function borderColor(): string
|
||||||
|
{
|
||||||
|
return match ($this) {
|
||||||
|
ScheduleStatus::TODO => '',
|
||||||
|
ScheduleStatus::INCOMING => 'warning',
|
||||||
|
ScheduleStatus::OVERDUE => 'danger',
|
||||||
|
ScheduleStatus::COMPLETED => 'success',
|
||||||
|
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -1,38 +1,82 @@
|
|||||||
<?php
|
<?php
|
||||||
namespace App\Helper;
|
namespace App\Helper;
|
||||||
|
|
||||||
|
use App\Services\OverdueReports;
|
||||||
|
use Symfony\Component\Validator\Constraints\Date;
|
||||||
|
|
||||||
class MonthHelper
|
class MonthHelper
|
||||||
{
|
{
|
||||||
|
public function __construct(private readonly OverdueReports $overdueReports){}
|
||||||
public function takeMonths() : array
|
public function takeMonths() : array
|
||||||
{
|
{
|
||||||
$startDate = new \DateTime("-6 months");
|
$startDate = new \DateTime("-6 months");
|
||||||
$startDate->modify("first day of this month");
|
$startDate->modify("first day of this month");
|
||||||
$return = [];
|
$return = [];
|
||||||
|
$overdueCounts = $this->overdueReports->getList();
|
||||||
for ($i=1; $i<=11; $i++) {
|
for ($i=1; $i<=11; $i++) {
|
||||||
$tmp = clone $startDate;
|
$tmp = clone $startDate;
|
||||||
$tmp->modify("+$i month");
|
$tmp->modify("+$i month");
|
||||||
$return[$i] = $tmp;
|
$return[$i] = [
|
||||||
|
'date' => $tmp,
|
||||||
|
'overdueCount' => 0
|
||||||
|
];
|
||||||
|
$key = $tmp->format('Y-m');
|
||||||
|
if (isset($overdueCounts[$key])) {
|
||||||
|
$return[$i]['overdueCount'] = $overdueCounts[$key];
|
||||||
|
unset($overdueCounts[$key]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (count($overdueCounts) > 0) {
|
||||||
|
$this->overdueReports->setLeftCount(array_sum($overdueCounts));
|
||||||
}
|
}
|
||||||
return $return;
|
return $return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public function getCurrentMonth(int $monthId) : \DateTime
|
public function getCurrentMonthDate(int $monthId) : ?\DateTime
|
||||||
{
|
{
|
||||||
|
if ($monthId < 0) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
$months = $this->takeMonths();
|
$months = $this->takeMonths();
|
||||||
if ($monthId==0) {
|
if ($monthId==0) {
|
||||||
$currentMonth = intval(date("n"));
|
$currentMonth = intval(date("n"));
|
||||||
|
|
||||||
foreach ($months as $mId => $monthObj) {
|
foreach ($months as $mId => $monthObj) {
|
||||||
if ($monthObj->format("m") == $currentMonth) {
|
$date = $monthObj['date']->format('m');
|
||||||
|
if ($date == $currentMonth) {
|
||||||
$monthCurrent = $monthObj;
|
$monthCurrent = $monthObj;
|
||||||
$monthId = $mId;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
$monthCurrent = $months[$monthId];
|
$monthCurrent = $months[$monthId];
|
||||||
}
|
}
|
||||||
return $monthCurrent;
|
return $monthCurrent['date'];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static function takeMonthNameForEmail(int $month) : string
|
||||||
|
{
|
||||||
|
$months = [
|
||||||
|
"stycznia", "lutego", "marca", "kwietnia", "maja", "czerwca", "lipca", "sierpnia", "września", "października", "listopada", "grudnia"
|
||||||
|
];
|
||||||
|
return $months[$month - 1] ?? "";
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function takeDateFormatWithPolishMonths(\DateTimeInterface $date, bool $showDays = true): string
|
||||||
|
{
|
||||||
|
$day = $date->format('d');
|
||||||
|
$month = $date->format('n');
|
||||||
|
$year = $date->format('Y');
|
||||||
|
$monthName = self::takeMonthNameForEmail($month);
|
||||||
|
|
||||||
|
$stringReturn = "";
|
||||||
|
if ($showDays) {
|
||||||
|
$stringReturn .= "$day ";
|
||||||
|
}
|
||||||
|
$stringReturn .= "$monthName $year";
|
||||||
|
|
||||||
|
return $stringReturn;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -26,7 +26,7 @@ class ReportsRepository extends ServiceEntityRepository
|
|||||||
return parent::findBy($criteria, $orderBy, $limit, $offset); // TODO: Change the autogenerated stub
|
return parent::findBy($criteria, $orderBy, $limit, $offset); // TODO: Change the autogenerated stub
|
||||||
}
|
}
|
||||||
|
|
||||||
public function findAllOverdue()
|
public function findAllOverdue(int $clientId = 0)
|
||||||
{
|
{
|
||||||
$dateEnd = new \DateTime();
|
$dateEnd = new \DateTime();
|
||||||
$dateEnd->modify("last day of previous month");
|
$dateEnd->modify("last day of previous month");
|
||||||
@@ -36,7 +36,12 @@ class ReportsRepository extends ServiceEntityRepository
|
|||||||
->andWhere('r.isDone = :isDone')
|
->andWhere('r.isDone = :isDone')
|
||||||
->setParameter('isDone', 0)
|
->setParameter('isDone', 0)
|
||||||
->setParameter('isDelete', 0)
|
->setParameter('isDelete', 0)
|
||||||
->setParameter('dateEnd', $dateEnd)
|
->setParameter('dateEnd', $dateEnd);
|
||||||
|
if ($clientId > 0) {
|
||||||
|
$reports->andWhere('r.client = :client');
|
||||||
|
$reports->setParameter('client', $clientId);
|
||||||
|
}
|
||||||
|
$reports = $reports
|
||||||
->orderBy("r.number","ASC")
|
->orderBy("r.number","ASC")
|
||||||
->getQuery()
|
->getQuery()
|
||||||
->getResult();
|
->getResult();
|
||||||
@@ -48,8 +53,9 @@ class ReportsRepository extends ServiceEntityRepository
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @return Reports[] Returns an array of Reports objects
|
* @return Reports[] Returns an array of Reports objects
|
||||||
|
* @throws \DateMalformedStringException
|
||||||
*/
|
*/
|
||||||
public function findAllInMonth(\DateTime $date): array
|
public function findAllInMonth(\DateTime $date, int $clientId = 0): array
|
||||||
{
|
{
|
||||||
$dateStart = clone $date;
|
$dateStart = clone $date;
|
||||||
$dateStart->modify("first day of this month");
|
$dateStart->modify("first day of this month");
|
||||||
@@ -61,13 +67,15 @@ class ReportsRepository extends ServiceEntityRepository
|
|||||||
->andWhere('r.isDelete = :deleted')
|
->andWhere('r.isDelete = :deleted')
|
||||||
->setParameter('dateStart', $dateStart->format('Y-m-d'))
|
->setParameter('dateStart', $dateStart->format('Y-m-d'))
|
||||||
->setParameter('dateEnd', $dateEnd->format('Y-m-d'))
|
->setParameter('dateEnd', $dateEnd->format('Y-m-d'))
|
||||||
->setParameter('deleted', 0)
|
->setParameter('deleted', 0);
|
||||||
|
if ($clientId > 0) {
|
||||||
|
$reports->andWhere('r.client = :client');
|
||||||
|
$reports->setParameter('client', $clientId);
|
||||||
|
}
|
||||||
|
$reports = $reports
|
||||||
->orderBy("r.number","ASC")
|
->orderBy("r.number","ASC")
|
||||||
// ->setMaxResults(10)
|
|
||||||
->getQuery()
|
->getQuery()
|
||||||
->getResult()
|
->getResult();
|
||||||
;
|
|
||||||
|
|
||||||
// $this->countReport($reports);
|
// $this->countReport($reports);
|
||||||
|
|
||||||
return $reports;
|
return $reports;
|
||||||
|
|||||||
@@ -11,25 +11,49 @@ use Doctrine\Persistence\ManagerRegistry;
|
|||||||
*/
|
*/
|
||||||
class ScheduleRepository extends ServiceEntityRepository
|
class ScheduleRepository extends ServiceEntityRepository
|
||||||
{
|
{
|
||||||
|
private const _OVERDUE_DAYS_START = 15;
|
||||||
|
private const _OVERDUE_DAYS_END = 30;
|
||||||
public function __construct(ManagerRegistry $registry)
|
public function __construct(ManagerRegistry $registry)
|
||||||
{
|
{
|
||||||
parent::__construct($registry, Schedule::class);
|
parent::__construct($registry, Schedule::class);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function findAllOverdue()
|
public function findAllOverdue(bool $onlyCount = false) : array|int
|
||||||
{
|
{
|
||||||
$dateEnd = new \DateTime("now");
|
$dateEnd = new \DateTime("now");
|
||||||
|
$dateEnd->modify("-".self::_OVERDUE_DAYS_START." days");
|
||||||
$reports = $this->createQueryBuilder('s')
|
$reports = $this->createQueryBuilder('s')
|
||||||
->where('s.isDone = :isDone')
|
->where('s.isDone = :isDone')
|
||||||
->andWhere('s.dateEnd < :dateEnd')
|
->andWhere('s.dateEnd < :dateEnd')
|
||||||
// ->andWhere('s.isDelete = :isDelete')
|
// ->andWhere('s.isDelete = :isDelete')
|
||||||
->setParameter('isDone', 0)
|
->setParameter('isDone', 0)
|
||||||
|
// ->setParameter('isDelete', 0)
|
||||||
|
->setParameter('dateEnd', $dateEnd);
|
||||||
|
|
||||||
|
if ($onlyCount) {
|
||||||
|
$reports->select('COUNT(s.id)');
|
||||||
|
return $reports->getQuery()->getSingleScalarResult();
|
||||||
|
}
|
||||||
|
|
||||||
|
return $reports->getQuery()->getResult();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function isOverdue(): bool
|
||||||
|
{
|
||||||
|
$dateEnd = new \DateTime("now");
|
||||||
|
$dateEnd->modify("-".self::_OVERDUE_DAYS_START." days");
|
||||||
|
$query = $this->createQueryBuilder('s')
|
||||||
|
->select('count(s.id)')
|
||||||
|
->where('s.isDone = :isDone')
|
||||||
|
->andWhere('s.dateEnd < :dateEnd')
|
||||||
|
// ->andWhere('s.isDelete = :isDelete')
|
||||||
|
->setParameter('isDone', 0)
|
||||||
// ->setParameter('isDelete', 0)
|
// ->setParameter('isDelete', 0)
|
||||||
->setParameter('dateEnd', $dateEnd)
|
->setParameter('dateEnd', $dateEnd)
|
||||||
->getQuery()
|
->getQuery()
|
||||||
->getResult();
|
->getSingleScalarResult();
|
||||||
|
|
||||||
return $reports;
|
trigger_error(var_export($query,true));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -39,9 +63,9 @@ class ScheduleRepository extends ServiceEntityRepository
|
|||||||
{
|
{
|
||||||
$date = new \DateTime();
|
$date = new \DateTime();
|
||||||
$dateStart = clone $date;
|
$dateStart = clone $date;
|
||||||
$dateStart->modify("-15 days");
|
$dateStart->modify("-".self::_OVERDUE_DAYS_START." days");
|
||||||
$dateEnd = clone $date;
|
$dateEnd = clone $date;
|
||||||
$dateEnd->modify("+30 days");
|
$dateEnd->modify("+".self::_OVERDUE_DAYS_END." days");
|
||||||
return $this->createQueryBuilder('r')
|
return $this->createQueryBuilder('r')
|
||||||
->where('r.dateEnd >= :dateStart')
|
->where('r.dateEnd >= :dateStart')
|
||||||
->andWhere('r.dateEnd <= :dateEnd')
|
->andWhere('r.dateEnd <= :dateEnd')
|
||||||
|
|||||||
@@ -0,0 +1,55 @@
|
|||||||
|
<?php
|
||||||
|
namespace App\Security;
|
||||||
|
|
||||||
|
use App\Entity\User;
|
||||||
|
use Symfony\Bundle\SecurityBundle\Security;
|
||||||
|
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
|
||||||
|
use Symfony\Component\Security\Core\Authorization\Voter\Voter;
|
||||||
|
|
||||||
|
class SchedulesVoter extends Voter
|
||||||
|
{
|
||||||
|
const VIEW = "scheduleView";
|
||||||
|
const EDIT = "scheduleEdit";
|
||||||
|
|
||||||
|
public function __construct(readonly private Security $security)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
protected function supports(string $attribute, mixed $subject): bool
|
||||||
|
{
|
||||||
|
if (!in_array($attribute, [self::VIEW, self::EDIT])) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true; }
|
||||||
|
|
||||||
|
protected function voteOnAttribute(string $attribute, mixed $subject, TokenInterface $token): bool
|
||||||
|
{
|
||||||
|
$user = $token->getUser();
|
||||||
|
if (!$user instanceof User) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return match ($attribute) {
|
||||||
|
self::VIEW => $this->canView(),
|
||||||
|
self::EDIT => $this->canEdit()
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private function canView(): bool
|
||||||
|
{
|
||||||
|
if ($this->canAll()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return $this->security->isGranted('ROLE_SCHEDULE_VIEW');
|
||||||
|
}
|
||||||
|
private function canEdit(): bool
|
||||||
|
{
|
||||||
|
if ($this->canAll()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return $this->canView();
|
||||||
|
}
|
||||||
|
private function canAll(): bool
|
||||||
|
{
|
||||||
|
return $this->security->isGranted('ROLE_ACCESS_ALL');
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -84,6 +84,7 @@ class AddReports
|
|||||||
$report->setNumber($numberOfReports + 1);
|
$report->setNumber($numberOfReports + 1);
|
||||||
$this->manager->persist($report);
|
$this->manager->persist($report);
|
||||||
$this->manager->flush();
|
$this->manager->flush();
|
||||||
|
$this->manager->getCache()->evictEntityRegion(Reports::class);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -107,6 +108,7 @@ class AddReports
|
|||||||
$report->setDateStart($dateToReport->modify("+".self::NEXT_REPORT_MONTH." months"));
|
$report->setDateStart($dateToReport->modify("+".self::NEXT_REPORT_MONTH." months"));
|
||||||
$this->manager->persist($report);
|
$this->manager->persist($report);
|
||||||
$this->manager->flush();
|
$this->manager->flush();
|
||||||
|
$this->manager->getCache()->evictEntityRegion(Reports::class);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,109 @@
|
|||||||
|
<?php
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace App\Services;
|
||||||
|
|
||||||
|
use App\Entity\Clients;
|
||||||
|
use Doctrine\ORM\EntityManager;
|
||||||
|
use Symfony\Contracts\HttpClient\HttpClientInterface;
|
||||||
|
|
||||||
|
class InvoiceServices
|
||||||
|
{
|
||||||
|
private Clients $clients;
|
||||||
|
private \DateTimeInterface $reportDate;
|
||||||
|
private string $apiKey;
|
||||||
|
public function __construct(
|
||||||
|
private readonly EntityManager $entityManager,
|
||||||
|
private readonly HttpClientInterface $curl){}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param Clients $clients
|
||||||
|
*/
|
||||||
|
public function setClients(Clients $clients): void
|
||||||
|
{
|
||||||
|
$this->clients = $clients;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setApiKey(string $api): void
|
||||||
|
{
|
||||||
|
$this->apiKey = $api;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param \DateTimeInterface $reportDate
|
||||||
|
*/
|
||||||
|
public function setReportDate(\DateTimeInterface $reportDate): void
|
||||||
|
{
|
||||||
|
$this->reportDate = $reportDate->modify('-1 month');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function send(): void
|
||||||
|
{
|
||||||
|
$this->curl->request(
|
||||||
|
'POST',
|
||||||
|
// 'https://kancelariakolczynski.fakturownia.pl/invoices.json',
|
||||||
|
'http://sprawozdania.docker/testapi',
|
||||||
|
[
|
||||||
|
'headers' => [
|
||||||
|
'Accept' => 'application/json',
|
||||||
|
],
|
||||||
|
'json' => $this->preparePost()
|
||||||
|
]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function postToJson(): string
|
||||||
|
{
|
||||||
|
return json_encode($this->preparePost());
|
||||||
|
}
|
||||||
|
|
||||||
|
private function preparePost() : array
|
||||||
|
{
|
||||||
|
if (!isset($this->clients) || !isset($this->reportDate)) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
$todayObj = new \DateTime("now");
|
||||||
|
$todayStr = $todayObj->format('Y-m-d');
|
||||||
|
$paymentToObj = new \DateTime("+7 days");
|
||||||
|
$paymentToStr = $paymentToObj->format('Y-m-d');
|
||||||
|
$monthStartPeriod = (clone $this->reportDate)->modify("-2 months")->format('m');
|
||||||
|
$periodStr = $monthStartPeriod . ' - ' . $this->reportDate->format('m') . '/' . $this->reportDate->format('Y');
|
||||||
|
|
||||||
|
$invoice = [
|
||||||
|
'kinds' => ["vat","proforma"],
|
||||||
|
'number' => null,
|
||||||
|
'sell_date' => $todayStr,
|
||||||
|
'issue_date' => $todayStr,
|
||||||
|
'payment_to' => $paymentToStr,
|
||||||
|
'buyer_name' => $this->clients->getStrName(),
|
||||||
|
'buyer_email' => $this->clients->getStrEmail(),
|
||||||
|
'buyer_tax_no' => $this->clients->getIntNIP(),
|
||||||
|
'positions' => [
|
||||||
|
[
|
||||||
|
'name' => "Przygotowanie sprawozdanie z wykonania układu za okres $periodStr",
|
||||||
|
'tax' => 23,
|
||||||
|
'total_price_gross' => 553.5
|
||||||
|
]
|
||||||
|
]
|
||||||
|
];
|
||||||
|
// "kind":"vat",
|
||||||
|
// "number": null,
|
||||||
|
// "sell_date": "2013-01-16",
|
||||||
|
// "issue_date": "2013-01-16",
|
||||||
|
// "payment_to": "2013-01-23",
|
||||||
|
// "seller_name": "Wystawca Sp. z o.o.",
|
||||||
|
// "seller_tax_no": "6272616681",
|
||||||
|
// "buyer_name": "Klient1 Sp. z o.o.",
|
||||||
|
// "buyer_email": "buyer@testemail.pl",
|
||||||
|
// "buyer_tax_no": "6272616681",
|
||||||
|
// "positions":[
|
||||||
|
// {"name":"Produkt A1", "tax":23, "total_price_gross":10.23, "quantity":1},
|
||||||
|
// {"name":"Produkt A2", "tax":0, "total_price_gross":50, "quantity":3}
|
||||||
|
// ]
|
||||||
|
|
||||||
|
return [
|
||||||
|
'api_token' => $this->apiKey,
|
||||||
|
'invoice' => $invoice,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
<?php
|
||||||
|
declare(strict_types=1);
|
||||||
|
namespace App\Services;
|
||||||
|
|
||||||
|
use App\Entity\Clients;
|
||||||
|
use App\Entity\Reports;
|
||||||
|
use App\Helper\MonthHelper;
|
||||||
|
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||||
|
use Twig\Environment;
|
||||||
|
|
||||||
|
class MailtoServices extends AbstractController
|
||||||
|
{
|
||||||
|
public function takeUrl(Reports $reports): string
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,61 @@
|
|||||||
|
<?php
|
||||||
|
declare(strict_types=1);
|
||||||
|
namespace App\Services;
|
||||||
|
use App\Entity\Clients;
|
||||||
|
use App\Entity\Reports;
|
||||||
|
use Doctrine\ORM\EntityManager;
|
||||||
|
|
||||||
|
class OverdueReports
|
||||||
|
{
|
||||||
|
private array $list;
|
||||||
|
private int $leftCount = 0;
|
||||||
|
private ?Clients $client = null;
|
||||||
|
public function __construct(private readonly EntityManager $entity){}
|
||||||
|
|
||||||
|
public function getList(): array
|
||||||
|
{
|
||||||
|
if(!isset($this->list)){
|
||||||
|
$this->list = $this->takeOverdueList();
|
||||||
|
}
|
||||||
|
return $this->list;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setLeftCount(int $leftCount): void
|
||||||
|
{
|
||||||
|
$this->leftCount = $leftCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setClient(?Clients $client): void
|
||||||
|
{
|
||||||
|
$this->client = $client;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getLeftCount(): int
|
||||||
|
{
|
||||||
|
return $this->leftCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function takeOverdueList() : array
|
||||||
|
{
|
||||||
|
$clientId = 0;
|
||||||
|
if($this->client){
|
||||||
|
$clientId = $this->client->getId();
|
||||||
|
}
|
||||||
|
$reports = $this->entity->getRepository(Reports::class)->findAllOverdue($clientId);
|
||||||
|
if (!$reports) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
$toReturn = [];
|
||||||
|
/** @var Reports $report */
|
||||||
|
foreach ($reports as $report) {
|
||||||
|
$date = $report->getDateStart()->format('Y-m');
|
||||||
|
if (!array_key_exists($date, $toReturn)) {
|
||||||
|
$toReturn[$date] = 1;
|
||||||
|
} else {
|
||||||
|
$toReturn[$date]++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $toReturn;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,6 +2,10 @@
|
|||||||
// src/Twig/AppExtension.php
|
// src/Twig/AppExtension.php
|
||||||
namespace App\Twig;
|
namespace App\Twig;
|
||||||
|
|
||||||
|
use App\Entity\Clients;
|
||||||
|
use App\Entity\Reports;
|
||||||
|
use App\Helper\MonthHelper;
|
||||||
|
use App\Services\AddReports;
|
||||||
use Twig\Extension\AbstractExtension;
|
use Twig\Extension\AbstractExtension;
|
||||||
use Twig\TwigFilter;
|
use Twig\TwigFilter;
|
||||||
use Twig\TwigFunction;
|
use Twig\TwigFunction;
|
||||||
@@ -19,6 +23,8 @@ class AppExtension extends AbstractExtension
|
|||||||
{
|
{
|
||||||
return [
|
return [
|
||||||
new TwigFunction('enum', [$this, 'enumChecker']),
|
new TwigFunction('enum', [$this, 'enumChecker']),
|
||||||
|
new TwigFunction('is_route_active', [$this, 'getActualRoute']),
|
||||||
|
new TwigFunction('getMailtoLink', [$this, 'getMailtoLink']),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -35,4 +41,33 @@ class AppExtension extends AbstractExtension
|
|||||||
{
|
{
|
||||||
return $currentEnum->name === $needEnumName;
|
return $currentEnum->name === $needEnumName;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getActualRoute(string $value, string $route): string
|
||||||
|
{
|
||||||
|
return $value === $route ? 'active' : '';
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getMailtoLink(Reports $reports): string
|
||||||
|
{
|
||||||
|
$subject = rawurlencode("Sprawozdanie z wykonania układu nr {$reports->getNumber()}");
|
||||||
|
$dateBase = (clone $reports->getDateStart())->modify("-1 month");
|
||||||
|
|
||||||
|
$template = "email/report.html.twig";
|
||||||
|
$dateStart = (clone $dateBase)->modify("-".(AddReports::NEXT_REPORT_MONTH-1)." months")->modify("first day of this month");
|
||||||
|
if ($reports->getNumber() === 1){
|
||||||
|
$template = "email/firstReport.html.twig";
|
||||||
|
$dateStart = $reports->getClient()->getDateLegitimacy();
|
||||||
|
}
|
||||||
|
$view = sprintf(
|
||||||
|
file_get_contents($_SERVER['PWD']."/templates/".$template),
|
||||||
|
MonthHelper::takeDateFormatWithPolishMonths($dateStart),
|
||||||
|
MonthHelper::takeDateFormatWithPolishMonths($dateBase->modify("last day of this month"))
|
||||||
|
);
|
||||||
|
$content = rawurlencode($view);
|
||||||
|
|
||||||
|
/** @var Clients $client */
|
||||||
|
$client = $reports->getClient();
|
||||||
|
|
||||||
|
return "mailto:{$client->getStrEmail()}?subject=$subject&body=$content";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
<!doctype html>
|
<!doctype html>
|
||||||
<html lang="pl">
|
<html lang="pl" data-bs-theme="">
|
||||||
<head>
|
<head>
|
||||||
{% if app.environment == "prod" %}
|
{% if app.environment == "prod" %}
|
||||||
<meta http-equiv="Content-Security-Policy" content="upgrade-insecure-requests" />
|
<meta http-equiv="Content-Security-Policy" content="upgrade-insecure-requests" />
|
||||||
@@ -7,9 +7,8 @@
|
|||||||
|
|
||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
<meta name="turbo-prefetch" content="false">
|
||||||
<title>{% block title %}Sprawozdania{% endblock %}</title>
|
<title>{% block title %}Sprawozdania{% endblock %}</title>
|
||||||
|
|
||||||
{% block stylesheets %}
|
{% block stylesheets %}
|
||||||
{# 'app' must match the first argument to addEntry() in webpack.config.js #}
|
{# 'app' must match the first argument to addEntry() in webpack.config.js #}
|
||||||
{{ encore_entry_link_tags('app') }}
|
{{ encore_entry_link_tags('app') }}
|
||||||
|
|||||||
@@ -1,132 +1,186 @@
|
|||||||
|
{% import 'reports/listInclude.html.twig' as sets %}
|
||||||
{% extends 'base.html.twig' %}
|
{% extends 'base.html.twig' %}
|
||||||
{% block body %}
|
{% block body %}
|
||||||
{% if client.isComplete %}
|
<div data-controller="customer-show">
|
||||||
<div class="alert alert-warning"><i class="fa-solid fa-circle-info"></i> Zakończono generowanie sprawozdań!</div>
|
{% if client.isComplete %}
|
||||||
{% endif %}
|
<div class="alert alert-warning"><i class="fa-solid fa-circle-info"></i> Zakończono generowanie sprawozdań!</div>
|
||||||
<div class="row row-cols-1 row-cols-md-2 g-2">
|
{% endif %}
|
||||||
<div class="col">
|
<div class="row row-cols-1 row-cols-md-2 g-2">
|
||||||
<div class="card text-center">
|
<div class="col">
|
||||||
<div class="card-header">
|
<div class="card text-center">
|
||||||
<h2>{{ client.strName }}</h2>
|
|
||||||
</div>
|
|
||||||
<ul class="list-group list-group-flush">
|
|
||||||
<li class="list-group-item"><span style="font-weight: bold">Adres: </span>{{ client.strAddress }}</li>
|
|
||||||
<li class="list-group-item"><span style="font-weight: bold">NIP: </span>{{ client.intNIP }}</li>
|
|
||||||
<li class="list-group-item"><span style="font-weight: bold">E-mail: </span>{{ client.strEmail }}</li>
|
|
||||||
<li class="list-group-item"><span style="font-weight: bold">Telefon: </span>{{ client.intPhone | phone }}</li>
|
|
||||||
<li class="list-group-item"><span style="font-weight: bold">Data prawomocności: </span>{{ client.dateLegitimacy | date("d-m-Y") }}</li>
|
|
||||||
<li class="list-group-item"><span style="font-weight: bold">Data obwieszczenia: </span>{{ client.dateProclamation | date("d-m-Y") }}</li>
|
|
||||||
{% if schedules %}
|
|
||||||
<li class="list-group-item list-group-item-{{ schedules.getStatus.backgroundColor }}">
|
|
||||||
<span style="font-weight: bold">Harmonogram: </span>
|
|
||||||
{% if schedules.isDone %}
|
|
||||||
wysłano: {{ schedules.getDateDone | date("d-m-Y H:i") }}
|
|
||||||
{% else %}
|
|
||||||
Pozostały czas: <span style="font-size: 1.2em">{{ schedules.getTimeLeft }}</span> dni
|
|
||||||
{% endif %}
|
|
||||||
</li>
|
|
||||||
{% endif %}
|
|
||||||
</ul>
|
|
||||||
<div class="card-footer" style="display: inline-flex;margin: auto;">
|
|
||||||
{% if is_granted('reportEdit') %}
|
|
||||||
<form action="{{ path('app_set_complete',{id: client.id}) }}" method="post" style="padding: 0 5px;">
|
|
||||||
<input type="hidden" name="isComplete" value="1">
|
|
||||||
<input type="hidden" name="token" value="{{ csrf_token("set-complete-item") }}">
|
|
||||||
<button class="btn btn-warning" type="submit">
|
|
||||||
{% if client.isComplete %}
|
|
||||||
Wznów
|
|
||||||
{% else %}
|
|
||||||
Zakończ
|
|
||||||
{% endif %}
|
|
||||||
</button>
|
|
||||||
</form>
|
|
||||||
{% endif %}
|
|
||||||
|
|
||||||
{% if not client.isComplete and is_granted('clientEdit') %}
|
|
||||||
<a href="{{ path('app_add_client',{id: client.id}) }}" class="btn btn-success">Edytuj</a>
|
|
||||||
{% endif %}
|
|
||||||
{% if is_granted('clientDelete') %}
|
|
||||||
<button class="btn btn-danger" type="button" data-bs-toggle="modal" data-bs-target="#removeConfirmModal">Usuń</button>
|
|
||||||
{% endif %}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{% if is_granted('reportView') %}
|
|
||||||
<div class="card text-center bg-light-subtle">
|
|
||||||
<div class="card-header">
|
<div class="card-header">
|
||||||
<h2>Sprawozdania</h2>
|
<h2>{{ client.strName }}</h2>
|
||||||
{% if not client.isComplete and is_granted('reportEdit') %}
|
|
||||||
<form action="{{ path('app_add_next_report') }}" method="post">
|
|
||||||
<input type="hidden" name="clientId" value="{{ client.id }}">
|
|
||||||
<input type="hidden" name="token" value="{{ csrf_token('add-next-report') }}">
|
|
||||||
<button type="submit" class="btn btn-primary">Dodaj następne sprawozdanie</button>
|
|
||||||
</form>
|
|
||||||
{% endif %}
|
|
||||||
</div>
|
</div>
|
||||||
<div class="card-body">
|
<ul class="list-group list-group-flush">
|
||||||
<ul class="list-group list-group-flush">
|
<li class="list-group-item"><span style="font-weight: bold">Adres: </span>{{ client.strAddress }}</li>
|
||||||
{% for report in reports %}
|
<li class="list-group-item"><span style="font-weight: bold">NIP: </span>{{ client.intNIP }}</li>
|
||||||
<li class="list-group-item d-flex align-items-center">
|
<li class="list-group-item"><span style="font-weight: bold">E-mail: </span>{{ client.strEmail }}</li>
|
||||||
<span class="badge rounded-pill text-bg-primary">{{ report.number }}</span>
|
<li class="list-group-item"><span style="font-weight: bold">Telefon: </span>{{ client.intPhone | phone }}</li>
|
||||||
<span class="badge rounded-pill text-bg-light">{{ report.getDateStart | date("Y-m-d") }}</span>
|
<li class="list-group-item"><span style="font-weight: bold">Data prawomocności: </span>{{ client.dateLegitimacy | date("d-m-Y") }}</li>
|
||||||
|
<li class="list-group-item"><span style="font-weight: bold">Data obwieszczenia: </span>{{ client.dateProclamation | date("d-m-Y") }}</li>
|
||||||
|
{% if schedules %}
|
||||||
|
<li class="list-group-item list-group-item-{{ schedules.getStatus.backgroundColor }}">
|
||||||
|
<span style="font-weight: bold">Harmonogram: </span>
|
||||||
|
{% if schedules.isDone %}
|
||||||
|
wysłano: {{ schedules.getDateDone | date("d-m-Y H:i") }}
|
||||||
|
{% else %}
|
||||||
|
Pozostały czas: <span style="font-size: 1.2em">{{ schedules.getTimeLeft }}</span> dni
|
||||||
|
{% endif %}
|
||||||
|
</li>
|
||||||
|
{% endif %}
|
||||||
|
</ul>
|
||||||
|
<div class="card-footer">
|
||||||
|
<div class='edit-client-group'>
|
||||||
|
{% if is_granted('reportView') %}
|
||||||
|
<div>
|
||||||
|
<a href="{{ path('app_base',{clientId: client.id}) }}" class="btn btn-outline-info">Wyświetl sprawozdania</a>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
{% if is_granted('reportEdit') %}
|
||||||
|
<div>
|
||||||
|
<form action="{{ path('app_set_complete',{id: client.id}) }}" method="post">
|
||||||
|
<input type="hidden" name="isComplete" value="1">
|
||||||
|
<input type="hidden" name="token" value="{{ csrf_token("set-complete-item") }}">
|
||||||
|
<button class="btn btn-outline-warning" type="submit">
|
||||||
|
{% if client.isComplete %}
|
||||||
|
Wznów
|
||||||
|
{% else %}
|
||||||
|
Zakończ
|
||||||
|
{% endif %}
|
||||||
|
</button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
{% for todo in report.getReportsTodos %}
|
{% if not client.isComplete and is_granted('clientEdit') %}
|
||||||
{% if report.isReportsTodo(todo.getName) %}
|
<div>
|
||||||
<span class="badge rounded-pill text-bg-{{ todo.getName.backgroundColor }}">
|
<a href="{{ path('app_add_client',{id: client.id}) }}" class="btn btn-outline-success">Edytuj</a>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
{% if is_granted('clientDelete') %}
|
||||||
|
<div>
|
||||||
|
<button class="btn btn-outline-danger" type="button" data-bs-toggle="modal" data-bs-target="#removeConfirmModal">Usuń</button>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% if is_granted('reportView') %}
|
||||||
|
<div class="card text-center bg-light-subtle">
|
||||||
|
<div class="card-header">
|
||||||
|
<h2>Sprawozdania</h2>
|
||||||
|
{% if not client.isComplete and is_granted('reportEdit') %}
|
||||||
|
<form action="{{ path('app_add_next_report') }}" method="post">
|
||||||
|
<input type="hidden" name="clientId" value="{{ client.id }}">
|
||||||
|
<input type="hidden" name="token" value="{{ csrf_token('add-next-report') }}">
|
||||||
|
<button type="submit" class="btn btn-outline-primary">Dodaj następne sprawozdanie</button>
|
||||||
|
</form>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
<div class="card-body">
|
||||||
|
<ul class="list-group list-group-flush">
|
||||||
|
{% for report in reports %}
|
||||||
|
<li class="list-group-item d-flex align-items-center"
|
||||||
|
data-action="click->customer-show#showModal"
|
||||||
|
data-customer-show-reportid-param="{{ report.id }}"
|
||||||
|
data-customer-show-date-param="{{ report.getDateStart | date("Y-m-d") }}"
|
||||||
|
>
|
||||||
|
<span class="badge rounded-pill text-bg-primary">{{ report.number }}</span>
|
||||||
|
<span class="badge rounded-pill text-bg-light">{{ report.getDateStart | date("Y-m-d") }}</span>
|
||||||
|
|
||||||
|
{% for todo in report.getReportsTodos %}
|
||||||
|
{% if report.isReportsTodo(todo.getName) %}
|
||||||
|
<span class="badge rounded-pill text-bg-{{ todo.getName.backgroundColor }}">
|
||||||
<i class="fa fa-solid fa-{{ todo.getName.takeIcon }}"> </i> {{ todo.getName.takeLang }}
|
<i class="fa fa-solid fa-{{ todo.getName.takeIcon }}"> </i> {{ todo.getName.takeLang }}
|
||||||
</span>
|
</span>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</li>
|
</li>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</ul>
|
</ul>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
<div class="col">
|
||||||
|
<div class="card">
|
||||||
|
<div class="card-header text-center"><h2>Notatka</h2></div>
|
||||||
|
{% if notes %}
|
||||||
|
<div class="card-body">
|
||||||
|
<p>
|
||||||
|
{% apply markdown_to_html %}
|
||||||
|
{{ notes.description }}
|
||||||
|
{% endapply %}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
{% if not client.isComplete and is_granted('clientEdit') %}
|
||||||
|
<div class="card-footer text-center">
|
||||||
|
<a href="{{ path('app_edit_client_note',{clientId: client.id}) }}" class="btn btn-success">Edytuj</a>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
|
||||||
</div>
|
<div class="card">
|
||||||
<div class="col">
|
<div class="card-header text-center"><h2>Oznaczenie</h2></div>
|
||||||
<div class="card">
|
|
||||||
<div class="card-header text-center"><h2>Notatka</h2></div>
|
|
||||||
{% if notes %}
|
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<p>
|
|
||||||
{% apply markdown_to_html %}
|
<form action="{{ path('app_client_highlight',{id: client.id}) }}" method="post">
|
||||||
{{ notes.description }}
|
<input type="hidden" name="token" value="{{ csrf_token('client-highlight') }}">
|
||||||
{% endapply %}
|
{% for status in highlightStatus %}
|
||||||
</p>
|
<button type="submit" name="highlight_id" value="{{ status.value }}" class="btn btn-{{ status.borderColor }}">
|
||||||
|
{{ status.buttonLang }}
|
||||||
|
</button>
|
||||||
|
{% endfor %}
|
||||||
|
</form>
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
</div>
|
||||||
{% if not client.isComplete and is_granted('clientEdit') %}
|
|
||||||
<div class="card-footer text-center">
|
|
||||||
<a href="{{ path('app_edit_client_note',{clientId: client.id}) }}" class="btn btn-success">Edytuj</a>
|
|
||||||
</div>
|
|
||||||
{% endif %}
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<div class="modal fade" id="removeConfirmModal" tabindex="-1" aria-labelledby="removeConfirmModalLabel" aria-hidden="true">
|
<div class="modal fade" id="removeConfirmModal" tabindex="-1" aria-labelledby="removeConfirmModalLabel" aria-hidden="true">
|
||||||
<div class="modal-dialog">
|
<div class="modal-dialog">
|
||||||
<div class="modal-content">
|
<div class="modal-content">
|
||||||
<div class="modal-header">
|
<div class="modal-header">
|
||||||
<h1 class="modal-title fs-5" id="removeConfirmModalLabel">Czy na pewno chcesz usunąć tego klienta?</h1>
|
<h1 class="modal-title fs-5" id="removeConfirmModalLabel">Czy na pewno chcesz usunąć tego klienta?</h1>
|
||||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-body">
|
<div class="modal-body">
|
||||||
Usunięcie klienta spowoduje wyczyszczenie wszystkich informacji z nim związanych (w tym sprawozdania, harmonogramy).<br>
|
Usunięcie klienta spowoduje wyczyszczenie wszystkich informacji z nim związanych (w tym sprawozdania, harmonogramy).<br>
|
||||||
<h3>Tej operacji nie można cofnąć!</h3>
|
<h3>Tej operacji nie można cofnąć!</h3>
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-footer">
|
<div class="modal-footer">
|
||||||
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
|
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
|
||||||
<form action="{{ path('app_client',{id:client.id}) }}" method="post">
|
<form action="{{ path('app_client',{id:client.id}) }}" method="post">
|
||||||
<input type="hidden" name="token" value="{{ csrf_token('delete-item') }}">
|
<input type="hidden" name="token" value="{{ csrf_token('delete-item') }}">
|
||||||
<input type="hidden" name="toDelete" value="1">
|
<input type="hidden" name="toDelete" value="1">
|
||||||
<input type="hidden" name="backUrl" value="{{ backUrl }}">
|
<input type="hidden" name="backUrl" value="{{ backUrl }}">
|
||||||
<button type="submit" class="btn btn-danger">Usuń</button>
|
<button type="submit" class="btn btn-danger">Usuń</button>
|
||||||
</form>
|
</form>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="modal fade" id="showReportModal" tabindex="-1" aria-labelledby="showReportModalLabel" aria-hidden="true">
|
||||||
|
<div class="modal-dialog">
|
||||||
|
<div class="modal-content">
|
||||||
|
<div class="modal-header">
|
||||||
|
<h1 class="modal-title fs-5" id="showReportModalLabel"></h1>
|
||||||
|
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||||
|
</div>
|
||||||
|
<div class="modal-body">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="allCardsReport">
|
||||||
|
{% for report in reports %}
|
||||||
|
{{ sets.cardView(report, reportStatus, reportToDoList) }}
|
||||||
|
{% endfor %}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
Szanowni Państwo,
|
||||||
|
w związku z prawomocnym zatwierdzeniem układu sąd ustanowił nadzorcą wykonania układu Pana Michała Kolczyńskiego. Wiąże się to z koniecznością składania do sądu kwartalnych sprawozdań z wykonania układu i realizacji płatności.
|
||||||
|
|
||||||
|
Co za tym idzie, zwracam się z uprzejmą prośbą o przesłanie potwierdzeń dokonanych przelewów rat układowych za okres od %s roku do %s roku
|
||||||
|
oraz o odpowiedź na następujące pytania:
|
||||||
|
|
||||||
|
1) Czy w okresie sprawozdawczym nastąpiły zwolnienia lub zatrudnienia pracowników;
|
||||||
|
|
||||||
|
2) Czy zbyty lub nabyty został jakiś majątek?
|
||||||
|
|
||||||
|
3) Proszę wymienić najważniejsze wydarzenia w działalności. (Czy udało się pozyskać nowych kontrahentów? Rozszerzenie rynku zbytu, nowe usługi, obniżenie kosztów utrzymania, nowi dostawcy?)
|
||||||
|
|
||||||
|
4) Czy nastąpiły jakieś zmiany organizacyjne?
|
||||||
|
|
||||||
|
Proszę o przekazanie niniejszych informacji oraz dokumentów w nieprzekraczalnym terminie 5 dni od otrzymania wiadomości.
|
||||||
|
|
||||||
|
W razie pytań lub wątpliwości proszę o kontakt z asystentem prowadzącym postępowanie.
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
Szanowni Państwo,
|
||||||
|
|
||||||
|
zwracam się z uprzejmą prośbą o przesłanie potwierdzeń dokonanych przelewów rat układowych za okres od %s roku do %s roku oraz o odpowiedź na następujące pytania:
|
||||||
|
|
||||||
|
1) Czy w okresie sprawozdawczym nastąpiły zwolnienia lub zatrudnienia pracowników;
|
||||||
|
|
||||||
|
2) Czy zbyty lub nabyty został jakiś majątek?
|
||||||
|
|
||||||
|
3) Proszę wymienić najważniejsze wydarzenia w działalności. (Czy udało się pozyskać nowych kontrahentów? Rozszerzenie rynku zbytu, nowe usługi, obniżenie kosztów utrzymania, nowi dostawcy?)
|
||||||
|
|
||||||
|
4) Czy nastąpiły jakieś zmiany organizacyjne?
|
||||||
|
|
||||||
|
Proszę o przekazanie niniejszych informacji oraz dokumentów w nieprzekraczalnym terminie 5 dni od otrzymania wiadomości.
|
||||||
|
|
||||||
|
W razie pytań lub wątpliwości proszę o kontakt z asystentem prowadzącym postępowanie.
|
||||||
@@ -1,40 +1,42 @@
|
|||||||
{% macro month_menu(routeName, months, currentMonth) %}
|
{% macro month_menu(routeName, months, currentMonth, countOverdueLeft, clientId, client) %}
|
||||||
<div class="row reports-months-all">
|
{% if client %}
|
||||||
<div class="col">
|
<div class="row justify-content-center">
|
||||||
<div class="card">
|
<div class="alert alert-info col-3 text-center " role="alert">
|
||||||
<a href="{{ path(routeName, {monthId:-1}) }}" class="btn {% if currentMonth is null %}btn-success{% else %}btn-secondary{% endif %}">Zaległe</a>
|
<h5 class="alert-heading"><strong>{{ client.strName }}</strong></h5>
|
||||||
|
<p>
|
||||||
|
<a href="{{ path(routeName,{monthId: 0}) }}" class="btn btn-outline-warning">Wróć do wszystkich</a>
|
||||||
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{% for id,month in months %}
|
{% endif %}
|
||||||
{% set isCurrent = currentMonth is not null and month | date("Y-m") == currentMonth | date("Y-m") %}
|
<div class="row reports-months-all">
|
||||||
<div class="col col-xxl-1 col-xl-2 col-lg-2 col-md-3 col-sm-3 col-4">
|
<ul class="nav nav-underline nav-fill">
|
||||||
<div class="card">
|
<li class="nav-item position-relative">
|
||||||
<a href="{{ path(routeName,{monthId: id}) }}" class="btn {% if isCurrent %}btn-success{% else %}btn-secondary{% endif %}">
|
<a href="{{ path(routeName, {monthId:-1, clientId:clientId}) }}" class="nav-link {% if currentMonth is null %}active{% endif %}">Zaległe</a>
|
||||||
|
{% if countOverdueLeft > 0 %}
|
||||||
|
<div class="spinner-grow spinner-grow-sm text-danger overdue"></div>
|
||||||
|
{% endif %}
|
||||||
|
</li>
|
||||||
|
{% for id,obj in months %}
|
||||||
|
{% set month = obj.date %}
|
||||||
|
{% set isCurrent = currentMonth is not null and month | date("Y-m") == currentMonth | date("Y-m") %}
|
||||||
|
<li class="nav-item position-relative"
|
||||||
|
{% if obj.overdueCount > 0 %}
|
||||||
|
data-toggle="tooltip" data-bs-placement="bottom" title="Zaległe sprawozdania do zrobienia"
|
||||||
|
{% endif %}
|
||||||
|
>
|
||||||
|
<a class="nav-link {% if isCurrent %} active{% endif %}" href="{{ path(routeName,{monthId: id, clientId:clientId}) }}">
|
||||||
{% if routeName=='app_schedule' %}
|
{% if routeName=='app_schedule' %}
|
||||||
{{ id }}
|
{{ id }}
|
||||||
{% else %}
|
{% else %}
|
||||||
{{ month | date("Y-m") }}
|
{{ month | date("Y-m") }}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</a>
|
</a>
|
||||||
</div>
|
{% if obj.overdueCount > 0 %}
|
||||||
</div>
|
<div class="spinner-grow spinner-grow-sm text-danger overdue"></div>
|
||||||
{% endfor %}
|
{% endif %}
|
||||||
{# <ul class="nav nav-tabs">#}
|
</li>
|
||||||
{# <li class="nav-item">#}
|
{% endfor %}
|
||||||
{# <a class="nav-link {% if currentMonth is null %}active{% endif %}" aria-current="page" href="{{ path(routeName, {monthId:-1}) }}">Zaległe</a>#}
|
</ul>
|
||||||
{# </li>#}
|
|
||||||
{# {% for id,month in months %}#}
|
|
||||||
{# {% set isCurrent = currentMonth is not null and month | date("Y-m") == currentMonth | date("Y-m") %}#}
|
|
||||||
{# <li class="nav-item">#}
|
|
||||||
{# <a class="nav-link {% if isCurrent %}active{% endif %}" href="{{ path(routeName,{monthId: id}) }}" aria-current="page">#}
|
|
||||||
{# {% if routeName=='app_schedule' %}#}
|
|
||||||
{# {{ id }}#}
|
|
||||||
{# {% else %}#}
|
|
||||||
{# {{ month | date("Y-m") }}#}
|
|
||||||
{# {% endif %}#}
|
|
||||||
{# </a>#}
|
|
||||||
{# </li>#}
|
|
||||||
{# {% endfor %}#}
|
|
||||||
{# </ul>#}
|
|
||||||
</div>
|
</div>
|
||||||
{% endmacro %}
|
{% endmacro %}
|
||||||
@@ -1,69 +1,56 @@
|
|||||||
{#<nav class="navbar navbar-inverse">#}
|
{% set route = app.request.attributes.get('_route') %}
|
||||||
{# <div class="container-fluid">#}
|
<nav class="navbar navbar-light navbar-expand-md justify-content-md-center justify-content-start">
|
||||||
{# <div class="navbar-header">#}
|
|
||||||
{# <a class="navbar-brand" href="{{ path('app_base') }}">WebSiteName</a>#}
|
|
||||||
{# </div>#}
|
|
||||||
{# <ul class="nav navbar-nav">#}
|
|
||||||
{# <li class="active"><a href="{{ path('app_base') }}">Home</a></li>#}
|
|
||||||
{# <li class="dropdown">#}
|
|
||||||
{# <a class="dropdown-toggle" data-toggle="dropdown" href="#">Klienci#}
|
|
||||||
{# <span class="caret"></span></a>#}
|
|
||||||
{# <ul class="dropdown-menu">#}
|
|
||||||
{# <li><a href="{{ path('app_customers_list') }}">Lista</a></li>#}
|
|
||||||
{# <li><a href="{{ path('app_base') }}">Dodaj klienta</a></li>#}
|
|
||||||
{# <li><a href="#">Page 1-3</a></li>#}
|
|
||||||
{# </ul>#}
|
|
||||||
{# </li>#}
|
|
||||||
{# <li><a href="#">Page 2</a></li>#}
|
|
||||||
{# <li><a href="#">Page 3</a></li>#}
|
|
||||||
{# </ul>#}
|
|
||||||
{# </div>#}
|
|
||||||
{#</nav>#}
|
|
||||||
<nav class="navbar navbar-expand-lg navbar-dark bg-primary">
|
|
||||||
<div class="container-fluid">
|
<div class="container-fluid">
|
||||||
<a class="navbar-brand" href="{{ path('index') }}">CRM</a>
|
<a class="navbar-brand" href="{{ path('index') }}">CRM</a>
|
||||||
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
|
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
|
||||||
<span class="navbar-toggler-icon"></span>
|
<span class="navbar-toggler-icon"></span>
|
||||||
</button>
|
</button>
|
||||||
<div class="collapse navbar-collapse" id="navbarSupportedContent">
|
<div class="navbar-collapse collapse justify-content-between align-items-center w-100" id="navbarSupportedContent">
|
||||||
<ul class="navbar-nav me-auto mb-2 mb-lg-0">
|
<ul class="navbar-nav">
|
||||||
{% if is_granted('reportView') %}
|
{% if is_granted('reportView') %}
|
||||||
<li class="nav-item">
|
<li class="nav-item">
|
||||||
<a class="nav-link active" aria-current="page" href="{{ path('app_base') }}">Sprawozdania</a>
|
<a class="nav-link {{ is_route_active('app_base', route) }}" aria-current="page" href="{{ path('app_base') }}">Sprawozdania</a>
|
||||||
</li>
|
</li>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
{% if is_granted('scheduleView') %}
|
||||||
<li class="nav-item">
|
<li class="nav-item">
|
||||||
<a class="nav-link active" aria-current="page" href="{{ path('app_schedule') }}">Harmonogramy</a>
|
<a class="nav-link {{ is_route_active('app_schedule', route) }}" aria-current="page" href="{{ path('app_schedule') }}">Harmonogramy</a>
|
||||||
</li>
|
</li>
|
||||||
|
{% endif %}
|
||||||
{% if is_granted('clientView') %}
|
{% if is_granted('clientView') %}
|
||||||
<li class="nav-item">
|
<li class="nav-item">
|
||||||
<a class="nav-link active" aria-current="page" href="{{ path('app_customers_list') }}">Klienci</a>
|
<a class="nav-link {{ is_route_active('app_customers_list', route) }}" aria-current="page" href="{{ path('app_customers_list') }}">Klienci</a>
|
||||||
</li>
|
</li>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{# <li class="nav-item dropdown">#}
|
|
||||||
{# <a class="nav-link dropdown-toggle" href="#" id="navbarDropdown" role="button" data-bs-toggle="dropdown" aria-expanded="false">#}
|
|
||||||
{# Klienci#}
|
|
||||||
{# </a>#}
|
|
||||||
{# <ul class="dropdown-menu" aria-labelledby="navbarDropdown">#}
|
|
||||||
{# <li><a class="dropdown-item" href="{{ path('app_customers_list') }}">Lista</a></li>#}
|
|
||||||
{# <li><a class="dropdown-item" href="{{ path('app_add_client') }}">Dodaj klienta</a></li>#}
|
|
||||||
{# <li><hr class="dropdown-divider"></li>#}
|
|
||||||
{# <li><a class="dropdown-item" href="#">Something else here</a></li>#}
|
|
||||||
{# </ul>#}
|
|
||||||
{# </li>#}
|
|
||||||
{# <li class="nav-item">#}
|
|
||||||
{# <a class="nav-link disabled" href="#" tabindex="-1" aria-disabled="true">Disabled</a>#}
|
|
||||||
{# </li>#}
|
|
||||||
</ul>
|
</ul>
|
||||||
{% if is_granted('clientAdd') %}
|
<ul class="navbar-nav">
|
||||||
<div class="d-flex">
|
<li class="nav-item">
|
||||||
<a href="{{ path('app_add_client') }}" class="btn btn-success btn-outline-dark" type="submit">Dodaj klienta</a>
|
<a href="{{ path('app_add_client') }}" class="btn btn-outline-success" type="submit"><i class="fa-regular fa-id-card"></i> Dodaj klienta</a>
|
||||||
</div>
|
</li>
|
||||||
{% endif %}
|
<li class="nav-item dropdown">
|
||||||
|
<a class="nav-link dropdown-toggle" href="#" id="navbarDropdown" role="button" data-bs-toggle="dropdown" aria-expanded="false">
|
||||||
|
<i class="fa-solid fa-circle-user"></i>
|
||||||
|
</a>
|
||||||
|
<ul class="dropdown-menu dropdown-menu-end" aria-labelledby="navbarDropdown">
|
||||||
|
<li data-controller="thememode">
|
||||||
|
<p class="nav-link dark" data-action="click->thememode#switch" data-thememode-mode-param="dark" data-bs-theme-value="dark"><i class="fa-solid fa-moon"></i> Tryb ciemny</p>
|
||||||
|
<p class="nav-link light" data-action="click->thememode#switch" data-thememode-mode-param="light" data-bs-theme-value="light"><i class="fa-regular fa-sun"></i> Tryb jasny</p>
|
||||||
|
</li>
|
||||||
|
<li><hr class="dropdown-divider"></li>
|
||||||
|
<li><a class="nav-link" href="{{ path('app_logout') }}"><i class="fa-solid fa-right-from-bracket"></i> Wyloguj</a></li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
{# {% if is_granted('clientAdd') %}#}
|
||||||
|
{# <div class="d-flex">#}
|
||||||
|
{# <a href="{{ path('app_add_client') }}" class="btn btn-outline-success" type="submit">Dodaj klienta</a>#}
|
||||||
|
{# </div>#}
|
||||||
|
{# {% endif %}#}
|
||||||
|
|
||||||
|
{# <div class="d-flex">#}
|
||||||
|
{# <a href="{{ path('app_logout') }}" class="btn btn-outline-primary" type="submit">Wyloguj</a>#}
|
||||||
|
{# </div>#}
|
||||||
|
|
||||||
<div class="d-flex">
|
|
||||||
<a href="{{ path('app_logout') }}" class="btn btn-primary btn-outline-dark" type="submit">Wyloguj</a>
|
|
||||||
</div>
|
|
||||||
{# <form class="d-flex">#}
|
{# <form class="d-flex">#}
|
||||||
{# <input class="form-control me-2" type="search" placeholder="Search" aria-label="Search">#}
|
{# <input class="form-control me-2" type="search" placeholder="Search" aria-label="Search">#}
|
||||||
{# <button class="btn btn-outline-success" type="submit">Search</button>#}
|
{# <button class="btn btn-outline-success" type="submit">Search</button>#}
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
{% import 'navigation/switch_months.html.twig' as navigation %}
|
{% import 'navigation/switch_months.html.twig' as navigation %}
|
||||||
{% import 'reports/listInclude.html.twig' as sets %}
|
{% import 'reports/listInclude.html.twig' as sets %}
|
||||||
{% block body %}
|
{% block body %}
|
||||||
{{ navigation.month_menu('app_base',months,currentMonth) }}
|
{{ navigation.month_menu('app_base',months,currentMonth,countOverdueLeft,clientId,client) }}
|
||||||
<div class="
|
<div class="
|
||||||
row
|
row
|
||||||
d-flex
|
d-flex
|
||||||
@@ -17,43 +17,7 @@
|
|||||||
<h3 class="card-header">{{ reports.status.takeLang }}</h3>
|
<h3 class="card-header">{{ reports.status.takeLang }}</h3>
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
{% for report in reports.reports %}
|
{% for report in reports.reports %}
|
||||||
<div class="card text-{{ reports.status.textColor }} border-dark report-one {{ reports.status.name | lower }}">
|
{{ sets.cardView(report, reports.status, reportToDoList,highlightStatus) }}
|
||||||
<div class="report-number">
|
|
||||||
<div class="badge bg-{{ reports.status.takeBadgeBg }} text-dark" data-toggle="tooltip" data-placement="bottom" title="Numer sprawozdania">{{ report.number }}</div>
|
|
||||||
</div>
|
|
||||||
{% if enum(reports.status, 'COMPLETE') %}
|
|
||||||
<div class="report-mark-uncompleted">
|
|
||||||
{# <div class="badge bg-danger text-dark" data-toggle="tooltip" data-placement="bottom" title="Oznacz jako nie zakończone">#}
|
|
||||||
|
|
||||||
<form action="{{ path('app_set_status_todo',{id:report.id}) }}" method="post">
|
|
||||||
<input type="hidden" name="token" value="{{ csrf_token('report-status') }}">
|
|
||||||
<input type="hidden" name="unDone" value="1">
|
|
||||||
<button type="submit" class="badge bg-danger text-dark" data-toggle="tooltip" data-placement="bottom" title="Oznacz jako nie zakończone"><i class="fa fa-solid fa-remove"></i></button>
|
|
||||||
</form>
|
|
||||||
|
|
||||||
{# </div>#}
|
|
||||||
</div>
|
|
||||||
{% endif %}
|
|
||||||
<div class="card-header">
|
|
||||||
<h5 class="card-title">
|
|
||||||
{% if is_granted('clientView') %}
|
|
||||||
<a href="{{ path('app_client',{id: report.client.id}) }}" class="link-{{ reports.status.linkColor }}">{{ report.client.strName }}</a>
|
|
||||||
{% else %}
|
|
||||||
{{ report.client.strName }}
|
|
||||||
{% endif %}
|
|
||||||
</h5>
|
|
||||||
</div>
|
|
||||||
{% if not enum(reports.status, 'COMPLETE') %}
|
|
||||||
<div class="card-body">
|
|
||||||
<p class="card-text">{{ sets.statusForm(report, reportToDoList, reports.status) }}</p>
|
|
||||||
</div>
|
|
||||||
{% endif %}
|
|
||||||
{% if enum(reports.status, 'WORKING') %}
|
|
||||||
<div class="card-footer bg-transparent">
|
|
||||||
{{ sets.progress(report, reportToDoList|length) }}
|
|
||||||
</div>
|
|
||||||
{% endif %}
|
|
||||||
</div>
|
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -3,20 +3,14 @@
|
|||||||
<input type="hidden" name="token" value="{{ csrf_token('report-status') }}">
|
<input type="hidden" name="token" value="{{ csrf_token('report-status') }}">
|
||||||
<div class="btn-group" role="group" aria-label="Todos">
|
<div class="btn-group" role="group" aria-label="Todos">
|
||||||
{% for todo in reportToDoList %}
|
{% for todo in reportToDoList %}
|
||||||
<input onchange="this.form.submit()"
|
<button type="submit" class="btn-check" name="{{ todo.value }}" value='1' id="checkboxToDo{{ todo.value }}Id{{ report.id }}"></button>
|
||||||
name="{{ todo.value }}"
|
<label class="btn
|
||||||
type="checkbox"
|
{% if report.isReportsTodo(todo) %}
|
||||||
class="btn-check"
|
btn-{{ reportEnum.checkboxColor }}
|
||||||
id="checkboxToDo{{ todo.value }}Id{{ report.id }}"
|
{% else %}
|
||||||
{% if report.isReportsTodo(todo) %}
|
btn-outline-{{ reportEnum.checkboxColor }}
|
||||||
checked="checked"
|
{% endif %}
|
||||||
{% endif %}
|
d-flex align-items-center"
|
||||||
{% if not is_granted('reportEdit') %}
|
|
||||||
disabled
|
|
||||||
{% endif %}
|
|
||||||
autocomplete="off"
|
|
||||||
>
|
|
||||||
<label class="btn btn-outline-{{ reportEnum.checkboxColor }} d-flex align-items-center"
|
|
||||||
for="checkboxToDo{{ todo.value }}Id{{ report.id }}"
|
for="checkboxToDo{{ todo.value }}Id{{ report.id }}"
|
||||||
data-toggle="tooltip" data-placement="bottom" title="{{ todo.takeLang }}">
|
data-toggle="tooltip" data-placement="bottom" title="{{ todo.takeLang }}">
|
||||||
<i class="fa fa-solid fa-{{ todo.takeIcon }}"> </i>
|
<i class="fa fa-solid fa-{{ todo.takeIcon }}"> </i>
|
||||||
@@ -40,3 +34,69 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{% endmacro %}
|
{% endmacro %}
|
||||||
|
|
||||||
|
{% macro cardView(report, groupStatus, reportToDoList, highlightStatus) %}
|
||||||
|
<div class="card text-{{ groupStatus.textColor }} report-one {{ groupStatus.name | lower }} border-{{ report.client.highlight.borderColor }}" data-report_id="{{ report.id }}">
|
||||||
|
<div class="report-number" data-bs-toggle="modal" data-bs-target="#editSchedule{{ report.id }}">
|
||||||
|
<div class="badge bg-{{ groupStatus.takeBadgeBg }} text-dark" data-toggle="tooltip" data-placement="bottom" title="Numer sprawozdania">{{ report.number }}</div>
|
||||||
|
</div>
|
||||||
|
{% if enum(groupStatus, 'COMPLETE') and false %}
|
||||||
|
<div class="report-mark-uncompleted">
|
||||||
|
<form action="{{ path('app_set_status_todo',{id:report.id}) }}" method="post">
|
||||||
|
<input type="hidden" name="token" value="{{ csrf_token('report-status') }}">
|
||||||
|
<input type="hidden" name="unDone" value="1">
|
||||||
|
<button type="submit" class="badge bg-danger" data-toggle="tooltip" data-placement="bottom" title="Oznacz jako nie zakończone"><i class="fa fa-solid fa-remove"></i></button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
<div class="card-header bg-{{ report.highlight.borderColor }}">
|
||||||
|
<h5 class="card-title">
|
||||||
|
{% if is_granted('clientView') %}
|
||||||
|
<a href="{{ path('app_client',{id: report.client.id}) }}" >{{ report.client.strName }}</a>
|
||||||
|
{% else %}
|
||||||
|
{{ report.client.strName }}
|
||||||
|
{% endif %}
|
||||||
|
</h5>
|
||||||
|
</div>
|
||||||
|
{# {% if not enum(groupStatus, 'COMPLETE') %}#}
|
||||||
|
<div class="card-body">
|
||||||
|
<p class="card-text">{{ _self.statusForm(report, reportToDoList, groupStatus) }}</p>
|
||||||
|
|
||||||
|
{% if is_granted('reportEdit') and not report.isEmailSend %}
|
||||||
|
<a class="btn btn-sm btn-outline-primary" href="{{ getMailtoLink(report) }}">Wyślij maila</a>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
</div>
|
||||||
|
{# {% endif %}#}
|
||||||
|
{% if enum(groupStatus, 'WORKING') %}
|
||||||
|
<div class="card-footer bg-transparent">
|
||||||
|
{{ _self.progress(report, reportToDoList|length) }}
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Modal -->
|
||||||
|
<div class="modal fade" id="editSchedule{{ report.id }}" tabindex="-1" aria-labelledby="editSchedule{{ report.id }}Label" aria-hidden="true">
|
||||||
|
<div class="modal-dialog">
|
||||||
|
<div class="modal-content">
|
||||||
|
<div class="modal-header">
|
||||||
|
<h1 class="modal-title fs-5" id="exampleModalLabel">Ustaw wyróżnienie sprawozdania</h1>
|
||||||
|
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||||
|
</div>
|
||||||
|
<div class="modal-body">
|
||||||
|
<form action="{{ path('app_report_highlight',{id: report.id}) }}" method="post">
|
||||||
|
<input type="hidden" name="token" value="{{ csrf_token('schedule-highlight') }}">
|
||||||
|
{% for status in highlightStatus %}
|
||||||
|
<button type="submit" name="highlight_id" value="{{ status.value }}" class="btn btn-{{ status.borderColor }}">
|
||||||
|
{{ status.buttonLang }}</button>
|
||||||
|
{% endfor %}
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
<div class="modal-footer">
|
||||||
|
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Zamknij</button>
|
||||||
|
{# <button type="button" class="btn btn-primary">Save changes</button>#}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endmacro %}
|
||||||
@@ -2,44 +2,42 @@
|
|||||||
{% import 'navigation/switch_months.html.twig' as navigation %}
|
{% import 'navigation/switch_months.html.twig' as navigation %}
|
||||||
{% block title %}Harmonogramy{% endblock %}
|
{% block title %}Harmonogramy{% endblock %}
|
||||||
{% block body %}
|
{% block body %}
|
||||||
{# {{ navigation.month_menu('app_schedule',months,currentMonth) }}#}
|
<div class="row reports-months-all">
|
||||||
<div class="row row-cols-2 reports-months-all">
|
<ul class="nav nav-underline nav-fill">
|
||||||
<div class="col">
|
<li class="nav-item position-relative">
|
||||||
<a href="{{ path('app_schedule', {typeId:2}) }}" class="card text-center text-white {% if typeId == 2 %}bg-primary{% else %}bg-secondary{% endif %}">
|
<a href="{{ path('app_schedule', {typeId:2}) }}" class="nav-link {% if typeId == 2 %}active{% endif %}">Zaległe</a>
|
||||||
<div class="card-title"><h2>Zaległe</h2></div>
|
{% if isOverdue %}
|
||||||
</a>
|
<div class="spinner-grow spinner-grow-sm text-danger overdue"></div>
|
||||||
{# <a href="{{ path('app_schedule', {monthId:-1}) }}" class="btn {% if currentMonth is null %}btn-success{% else %}btn-secondary{% endif %}">Zaległe</a>#}
|
{% endif %}
|
||||||
</div>
|
</li>
|
||||||
<div class="col">
|
<li class="nav-item">
|
||||||
<a href="{{ path('app_schedule', {typeId:1}) }}" class="card text-center text-white {% if typeId == 1 %}bg-primary{% else %}bg-secondary{% endif %}">
|
<a href="{{ path('app_schedule', {typeId:1}) }}" class="nav-link {% if typeId == 1 %}active{% endif %}">Aktualne</a>
|
||||||
<div class="card-title"><h2>Aktualne</h2></div>
|
</li>
|
||||||
</a>
|
</ul>
|
||||||
{# <a href="{{ path('app_schedule', {monthId:-1}) }}" class="btn {% if currentMonth is null %}btn-success{% else %}btn-secondary{% endif %}">Zaległe</a>#}
|
|
||||||
</div>
|
|
||||||
{# <div class="col">#}
|
|
||||||
{# <a href="{{ path('app_schedule', {monthId:1}) }}" class="btn {% if currentMonth is null %}btn-success{% else %}btn-secondary{% endif %}">Aktualne</a>#}
|
|
||||||
{# </div>#}
|
|
||||||
</div>
|
</div>
|
||||||
<div class="row row-cols-auto reports-all">
|
<div class="row row-cols-auto schedule-all">
|
||||||
{% for schedule in schedules %}
|
{% for schedule in schedules %}
|
||||||
<div class="col">
|
<div class="col">
|
||||||
<div class="card text-white bg-{{ schedule.getStatus.backgroundColor }}">
|
<div class="card border-{{ schedule.getStatus.borderColor }}">
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<h5 class="card-title">
|
<h5 class="card-title">
|
||||||
{% if is_granted('clientView') %}
|
{% if is_granted('clientView') %}
|
||||||
<a href="{{ path('app_client',{id: schedule.client.id}) }}" class="link-dark">{{ schedule.client.strName }}</a>
|
<a href="{{ path('app_client',{id: schedule.client.id}) }}">{{ schedule.client.strName }}</a>
|
||||||
{% else %}
|
{% else %}
|
||||||
<div class="link-dark">{{ schedule.client.strName }}</div>
|
<div class="link-dark">{{ schedule.client.strName }}</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</h5>
|
</h5>
|
||||||
|
{% if enum(schedule.getStatus, 'OVERDUE') %}
|
||||||
|
<h6 class="card-subtitle text-muted text-danger-emphasis">Czas minął: {{ schedule.getTimeLeft }} dni</h6>
|
||||||
|
<div class="spinner-grow spinner-grow-sm text-danger overdue"></div>
|
||||||
|
{% else %}
|
||||||
<h6 class="card-subtitle text-muted">Pozostały czas: {{ schedule.getTimeLeft }} dni</h6>
|
<h6 class="card-subtitle text-muted">Pozostały czas: {{ schedule.getTimeLeft }} dni</h6>
|
||||||
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
<div class="card-footer">
|
<div class="card-footer">
|
||||||
<form action="{{ path('app_schedule_status') }}" method="post">
|
<form action="{{ path('app_schedule_status',{id:schedule.id}) }}" method="post">
|
||||||
<input type="hidden" name="token" value="{{ csrf_token('schedule-status') }}">
|
<input type="hidden" name="token" value="{{ csrf_token('schedule-status') }}">
|
||||||
<input type="hidden" name="scheduleId" value="{{ schedule.id }}">
|
<button type="submit" class="btn btn-outline-success w-100">Wysłano</button>
|
||||||
|
|
||||||
<button type="submit" class="btn btn-success">Wysłano</button>
|
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -72,6 +72,14 @@ Encore
|
|||||||
|
|
||||||
// uncomment if you're having problems with a jQuery plugin
|
// uncomment if you're having problems with a jQuery plugin
|
||||||
//.autoProvidejQuery()
|
//.autoProvidejQuery()
|
||||||
|
.configureTerserPlugin(options => {
|
||||||
|
options.terserOptions = {
|
||||||
|
output: {
|
||||||
|
comments: false
|
||||||
|
},
|
||||||
|
sourceMap: true
|
||||||
|
}
|
||||||
|
})
|
||||||
;
|
;
|
||||||
|
|
||||||
module.exports = Encore.getWebpackConfig();
|
module.exports = Encore.getWebpackConfig();
|
||||||
|
|||||||
@@ -18,8 +18,9 @@ RUN apt-get install -y \
|
|||||||
libwebp-dev \
|
libwebp-dev \
|
||||||
libfreetype6-dev \
|
libfreetype6-dev \
|
||||||
libonig-dev \
|
libonig-dev \
|
||||||
npm \
|
npm
|
||||||
&& docker-php-ext-configure zip \
|
|
||||||
|
RUN docker-php-ext-configure zip \
|
||||||
&& docker-php-ext-install zip intl
|
&& docker-php-ext-install zip intl
|
||||||
RUN apt-get install -y libgd3 libgd-dev && rm -rf /var/lib/apt/lists/*
|
RUN apt-get install -y libgd3 libgd-dev && rm -rf /var/lib/apt/lists/*
|
||||||
RUN docker-php-ext-configure gd --with-jpeg
|
RUN docker-php-ext-configure gd --with-jpeg
|
||||||
@@ -37,6 +38,7 @@ COPY --from=composer /usr/bin/composer /usr/bin/composer
|
|||||||
COPY --chown=www-data:www-data ./project /var/www/html
|
COPY --chown=www-data:www-data ./project /var/www/html
|
||||||
|
|
||||||
WORKDIR /var/www/html
|
WORKDIR /var/www/html
|
||||||
|
ENV COMPOSER_ALLOW_SUPERUSER=1
|
||||||
RUN composer install --no-dev --no-interaction --no-autoloader --no-scripts
|
RUN composer install --no-dev --no-interaction --no-autoloader --no-scripts
|
||||||
|
|
||||||
RUN npm install
|
RUN npm install
|
||||||
@@ -44,10 +46,7 @@ RUN npm run build
|
|||||||
RUN apt-get purge --auto-remove -y npm
|
RUN apt-get purge --auto-remove -y npm
|
||||||
|
|
||||||
|
|
||||||
ENV COMPOSER_ALLOW_SUPERUSER=1
|
|
||||||
RUN composer dump-autoload --optimize
|
RUN composer dump-autoload --optimize
|
||||||
|
|
||||||
|
|
||||||
RUN mv .env.prod .env
|
RUN mv .env.prod .env
|
||||||
COPY services/config/nginx-site.conf /etc/nginx/sites-enabled/default
|
COPY services/config/nginx-site.conf /etc/nginx/sites-enabled/default
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user