Facturacion
This commit is contained in:
@ -11,4 +11,5 @@ interface Connection
|
|||||||
public function prepare(string $query): PDOStatement;
|
public function prepare(string $query): PDOStatement;
|
||||||
public function execute(string $query, ?array $data = null): PDOStatement;
|
public function execute(string $query, ?array $data = null): PDOStatement;
|
||||||
public function getPDO(): PDO;
|
public function getPDO(): PDO;
|
||||||
|
public function getQueryBuilder(): Query\Builder;
|
||||||
}
|
}
|
||||||
|
@ -5,4 +5,5 @@ use JsonSerializable;
|
|||||||
|
|
||||||
interface Model extends JsonSerializable
|
interface Model extends JsonSerializable
|
||||||
{
|
{
|
||||||
|
public function addFactory(string $property, Repository\Factory $factory): Model;
|
||||||
}
|
}
|
||||||
|
15
app/common/Define/Query.php
Normal file
15
app/common/Define/Query.php
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
<?php
|
||||||
|
namespace Incoviba\Common\Define;
|
||||||
|
|
||||||
|
interface Query
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function build(): string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function __toString(): string;
|
||||||
|
}
|
33
app/common/Define/Query/Builder.php
Normal file
33
app/common/Define/Query/Builder.php
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
<?php
|
||||||
|
namespace Incoviba\Common\Define\Query;
|
||||||
|
|
||||||
|
interface Builder
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @param string $table_name
|
||||||
|
* @return Create
|
||||||
|
*/
|
||||||
|
public function create(string $table_name): Create;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string|array $columns
|
||||||
|
* @return Select
|
||||||
|
*/
|
||||||
|
public function select(string|array $columns = '*'): Select;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Insert
|
||||||
|
*/
|
||||||
|
public function insert(): Insert;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $table
|
||||||
|
* @return Update
|
||||||
|
*/
|
||||||
|
public function update(string $table): Update;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Delete
|
||||||
|
*/
|
||||||
|
public function delete(): Delete;
|
||||||
|
}
|
31
app/common/Define/Query/Create.php
Normal file
31
app/common/Define/Query/Create.php
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
<?php
|
||||||
|
namespace Incoviba\Common\Define\Query;
|
||||||
|
|
||||||
|
use Incoviba\Common\Define;
|
||||||
|
|
||||||
|
interface Create extends Define\Query
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @param string $name
|
||||||
|
* @return Create
|
||||||
|
*/
|
||||||
|
public function table(string $name): Create;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string|Create\CreateDefinition|array $create_definitions
|
||||||
|
* @return Create
|
||||||
|
*/
|
||||||
|
public function definitions(string|Create\CreateDefinition|array $create_definitions): Create;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string|array $table_options
|
||||||
|
* @return Create
|
||||||
|
*/
|
||||||
|
public function options(string|array $table_options): Create;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string|array $partition_options
|
||||||
|
* @return Create
|
||||||
|
*/
|
||||||
|
public function partition(string|array $partition_options): Create;
|
||||||
|
}
|
59
app/common/Define/Query/Create/CreateDefinition.php
Normal file
59
app/common/Define/Query/Create/CreateDefinition.php
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
<?php
|
||||||
|
namespace Incoviba\Common\Define\Query\Create;
|
||||||
|
|
||||||
|
interface CreateDefinition
|
||||||
|
{
|
||||||
|
const RESTRICT = 0;
|
||||||
|
const CASCADE = 1;
|
||||||
|
const SET_NULL = 2;
|
||||||
|
const NO_ACTION = 3;
|
||||||
|
const SET_DEFAULT = 4;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $name
|
||||||
|
* @return CreateDefinition
|
||||||
|
*/
|
||||||
|
public function name(string $name): CreateDefinition;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $type
|
||||||
|
* @param int|null $size
|
||||||
|
* @return CreateDefinition
|
||||||
|
*/
|
||||||
|
public function type(string $type, ?int $size = null): CreateDefinition;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return CreateDefinition
|
||||||
|
*/
|
||||||
|
public function primary(): CreateDefinition;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return CreateDefinition
|
||||||
|
*/
|
||||||
|
public function autoIncrement(): CreateDefinition;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return CreateDefinition
|
||||||
|
*/
|
||||||
|
public function unsigned(): CreateDefinition;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param mixed $value
|
||||||
|
* @return CreateDefinition
|
||||||
|
*/
|
||||||
|
public function default(mixed $value): CreateDefinition;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $reference_table
|
||||||
|
* @param string $reference_column
|
||||||
|
* @param int $on_delete
|
||||||
|
* @param int $on_update
|
||||||
|
* @return CreateDefinition
|
||||||
|
*/
|
||||||
|
public function foreign(string $reference_table, string $reference_column = 'id', int $on_delete = CreateDefinition::CASCADE, int $on_update = CreateDefinition::CASCADE): CreateDefinition;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function __toString(): string;
|
||||||
|
}
|
12
app/common/Define/Query/Delete.php
Normal file
12
app/common/Define/Query/Delete.php
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
<?php
|
||||||
|
namespace Incoviba\Common\Define\Query;
|
||||||
|
|
||||||
|
use Incoviba\Common\Define;
|
||||||
|
|
||||||
|
interface Delete extends Define\Query
|
||||||
|
{
|
||||||
|
public function from(string $table): Delete;
|
||||||
|
public function where(string|array $conditions): Delete;
|
||||||
|
public function order(string|array $sorting): Delete;
|
||||||
|
public function limit(int $limit): Delete;
|
||||||
|
}
|
32
app/common/Define/Query/Insert.php
Normal file
32
app/common/Define/Query/Insert.php
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
<?php
|
||||||
|
namespace Incoviba\Common\Define\Query;
|
||||||
|
|
||||||
|
use Incoviba\Common\Define;
|
||||||
|
|
||||||
|
interface Insert extends Define\Query
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @param string $table
|
||||||
|
* @param array|null $columns
|
||||||
|
* @return Insert
|
||||||
|
*/
|
||||||
|
public function into(string $table, ?array $columns = null): Insert;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param array $columns
|
||||||
|
* @return Insert
|
||||||
|
*/
|
||||||
|
public function columns(array $columns): Insert;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param array $values
|
||||||
|
* @return Insert
|
||||||
|
*/
|
||||||
|
public function values(array $values): Insert;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param Select $select
|
||||||
|
* @return Insert
|
||||||
|
*/
|
||||||
|
public function select(Select $select): Insert;
|
||||||
|
}
|
62
app/common/Define/Query/Select.php
Normal file
62
app/common/Define/Query/Select.php
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
<?php
|
||||||
|
namespace Incoviba\Common\Define\Query;
|
||||||
|
|
||||||
|
use Incoviba\Common\Define;
|
||||||
|
|
||||||
|
interface Select extends Define\Query
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @param string|array $expressions
|
||||||
|
* @return Select
|
||||||
|
*/
|
||||||
|
public function columns(string|array $expressions): Select;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $table
|
||||||
|
* @return Select
|
||||||
|
*/
|
||||||
|
public function from(string $table): Select;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string|array $joins
|
||||||
|
* @return Select
|
||||||
|
*/
|
||||||
|
public function joined(string|array $joins): Select;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string|array $conditions
|
||||||
|
* @return Select
|
||||||
|
*/
|
||||||
|
public function where(string|array $conditions): Select;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string|array $grouping
|
||||||
|
* @return Select
|
||||||
|
*/
|
||||||
|
public function group(string|array $grouping): Select;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string|array $conditions
|
||||||
|
* @return Select
|
||||||
|
*/
|
||||||
|
public function having(string|array $conditions): Select;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string|array $sorting
|
||||||
|
* @return Select
|
||||||
|
*/
|
||||||
|
public function order(string|array $sorting): Select;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param int $limit
|
||||||
|
* @param int|null $offset
|
||||||
|
* @return Select
|
||||||
|
*/
|
||||||
|
public function limit(int $limit, ?int $offset = null): Select;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param int $offset
|
||||||
|
* @return Select
|
||||||
|
*/
|
||||||
|
public function offset(int $offset): Select;
|
||||||
|
}
|
13
app/common/Define/Query/Update.php
Normal file
13
app/common/Define/Query/Update.php
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
<?php
|
||||||
|
namespace Incoviba\Common\Define\Query;
|
||||||
|
|
||||||
|
use Incoviba\Common\Define;
|
||||||
|
|
||||||
|
interface Update extends Define\Query
|
||||||
|
{
|
||||||
|
public function table(string $table): Update;
|
||||||
|
public function set(string|array $column_pairs): Update;
|
||||||
|
public function where(string|array $conditions): Update;
|
||||||
|
public function order(string|array $ordering): Update;
|
||||||
|
public function limit(int $limit): Update;
|
||||||
|
}
|
@ -1,6 +1,8 @@
|
|||||||
<?php
|
<?php
|
||||||
namespace Incoviba\Common\Define\Repository;
|
namespace Incoviba\Common\Define\Repository;
|
||||||
|
|
||||||
|
use Incoviba\Common\Define\Model;
|
||||||
|
|
||||||
interface Mapper
|
interface Mapper
|
||||||
{
|
{
|
||||||
public function setProperty(string $property): Mapper;
|
public function setProperty(string $property): Mapper;
|
||||||
@ -12,4 +14,6 @@ interface Mapper
|
|||||||
public function hasFunction(): bool;
|
public function hasFunction(): bool;
|
||||||
public function hasFactory(): bool;
|
public function hasFactory(): bool;
|
||||||
public function hasDefault(): bool;
|
public function hasDefault(): bool;
|
||||||
|
|
||||||
|
public function parse(Model &$model, string $column, ?array $data): bool;
|
||||||
}
|
}
|
||||||
|
12
app/common/Ideal/Query.php
Normal file
12
app/common/Ideal/Query.php
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
<?php
|
||||||
|
namespace Incoviba\Common\Ideal;
|
||||||
|
|
||||||
|
use Incoviba\Common\Define;
|
||||||
|
|
||||||
|
abstract class Query implements Define\Query
|
||||||
|
{
|
||||||
|
public function __toString(): string
|
||||||
|
{
|
||||||
|
return $this->build();
|
||||||
|
}
|
||||||
|
}
|
@ -31,18 +31,25 @@ abstract class Repository implements Define\Repository
|
|||||||
|
|
||||||
public function remove(Define\Model $model): void
|
public function remove(Define\Model $model): void
|
||||||
{
|
{
|
||||||
$query = "DELETE FROM `{$this->getTable()}` WHERE `{$this->getKey()}` = ?";
|
$query = $this->connection->getQueryBuilder()
|
||||||
$this->connection->execute($query, [$model->getId()]);
|
->delete()->from($this->getTable())
|
||||||
|
->where("{$this->getKey()} = ?");
|
||||||
|
$this->connection->execute($query, [$model->id]);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function fetchById(int $id): Define\Model
|
public function fetchById(int $id): Define\Model
|
||||||
{
|
{
|
||||||
$query = "SELECT * FROM `{$this->getTable()}` WHERE `{$this->getKey()}` = ?";
|
$query = $this->connection->getQueryBuilder()
|
||||||
|
->select()
|
||||||
|
->from($this->getTable())
|
||||||
|
->where("{$this->getKey()} = ?");
|
||||||
return $this->fetchOne($query, [$id]);
|
return $this->fetchOne($query, [$id]);
|
||||||
}
|
}
|
||||||
public function fetchAll(): array
|
public function fetchAll(): array
|
||||||
{
|
{
|
||||||
$query = "SELECT * FROM `{$this->getTable()}`";
|
$query = $this->connection->getQueryBuilder()
|
||||||
|
->select()
|
||||||
|
->from($this->getTable());
|
||||||
return $this->fetchMany($query);
|
return $this->fetchMany($query);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -96,9 +103,11 @@ abstract class Repository implements Define\Repository
|
|||||||
}
|
}
|
||||||
protected function saveNew(array $columns, array $values): int
|
protected function saveNew(array $columns, array $values): int
|
||||||
{
|
{
|
||||||
$columns_string = implode(', ', array_map(function($column) {return "`{$column}`";}, $columns));
|
$query = $this->connection->getQueryBuilder()
|
||||||
$columns_questions = implode(', ', array_fill(0, count($columns), '?'));
|
->insert()
|
||||||
$query = "INSERT INTO `{$this->getTable()}` ({$columns_string}) VALUES ($columns_questions)";
|
->into($this->getTable())
|
||||||
|
->columns($columns)
|
||||||
|
->values(array_fill(0, count($columns), '?'));
|
||||||
$this->connection->execute($query, $values);
|
$this->connection->execute($query, $values);
|
||||||
return $this->connection->getPDO()->lastInsertId();
|
return $this->connection->getPDO()->lastInsertId();
|
||||||
}
|
}
|
||||||
@ -117,7 +126,10 @@ abstract class Repository implements Define\Repository
|
|||||||
return $model;
|
return $model;
|
||||||
}
|
}
|
||||||
$columns_string = implode(', ', array_map(function($property) {return "`{$property}` = ?";}, $changes));
|
$columns_string = implode(', ', array_map(function($property) {return "`{$property}` = ?";}, $changes));
|
||||||
$query = "UPDATE `{$this->getTable()}` SET {$columns_string} WHERE `{$this->getKey()}` = ?";
|
$query = $this->connection->getQueryBuilder()
|
||||||
|
->update($this->getTable())
|
||||||
|
->set($columns_string)
|
||||||
|
->where("{$this->getKey()} = ?");
|
||||||
$values []= $model->{$this->getKey()};
|
$values []= $model->{$this->getKey()};
|
||||||
$this->connection->execute($query, $values);
|
$this->connection->execute($query, $values);
|
||||||
return $this->fetchById($model->{$this->getKey()});
|
return $this->fetchById($model->{$this->getKey()});
|
||||||
|
@ -8,7 +8,7 @@ use Incoviba\Common\Define;
|
|||||||
|
|
||||||
class Connection implements Define\Connection
|
class Connection implements Define\Connection
|
||||||
{
|
{
|
||||||
public function __construct(protected Define\Database $database) {}
|
public function __construct(protected Define\Database $database, protected Database\Query\Builder $queryBuilder) {}
|
||||||
|
|
||||||
protected PDO $connection;
|
protected PDO $connection;
|
||||||
public function connect(): Define\Connection
|
public function connect(): Define\Connection
|
||||||
@ -27,6 +27,10 @@ class Connection implements Define\Connection
|
|||||||
$this->connect();
|
$this->connect();
|
||||||
return $this->connection;
|
return $this->connection;
|
||||||
}
|
}
|
||||||
|
public function getQueryBuilder(): Database\Query\Builder
|
||||||
|
{
|
||||||
|
return $this->queryBuilder;
|
||||||
|
}
|
||||||
|
|
||||||
public function query(string $query): PDOStatement
|
public function query(string $query): PDOStatement
|
||||||
{
|
{
|
||||||
|
29
app/common/Implement/Database/Query/Builder.php
Normal file
29
app/common/Implement/Database/Query/Builder.php
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
<?php
|
||||||
|
namespace Incoviba\Common\Implement\Database\Query;
|
||||||
|
|
||||||
|
use Incoviba\Common\Define;
|
||||||
|
|
||||||
|
class Builder implements Define\Query\Builder
|
||||||
|
{
|
||||||
|
public function create(string $table_name): Create
|
||||||
|
{
|
||||||
|
return (new Create())->table($table_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function select(array|string $columns = '*'): Select
|
||||||
|
{
|
||||||
|
return (new Select())->columns($columns);
|
||||||
|
}
|
||||||
|
public function insert(): Insert
|
||||||
|
{
|
||||||
|
return new Insert();
|
||||||
|
}
|
||||||
|
public function update(string $table): Update
|
||||||
|
{
|
||||||
|
return (new Update())->table($table);
|
||||||
|
}
|
||||||
|
public function delete(): Delete
|
||||||
|
{
|
||||||
|
return new Delete();
|
||||||
|
}
|
||||||
|
}
|
102
app/common/Implement/Database/Query/Create.php
Normal file
102
app/common/Implement/Database/Query/Create.php
Normal file
@ -0,0 +1,102 @@
|
|||||||
|
<?php
|
||||||
|
namespace Incoviba\Common\Implement\Database\Query;
|
||||||
|
|
||||||
|
use Incoviba\Common\Define;
|
||||||
|
use Incoviba\Common\Ideal;
|
||||||
|
|
||||||
|
class Create extends Ideal\Query implements Define\Query\Create
|
||||||
|
{
|
||||||
|
protected string $name;
|
||||||
|
protected array $definitions;
|
||||||
|
protected array $options;
|
||||||
|
protected array $partitions;
|
||||||
|
|
||||||
|
public function table(string $name): Define\Query\Create
|
||||||
|
{
|
||||||
|
$this->name = $name;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
public function definitions(Define\Query\Create\CreateDefinition|array|string $create_definitions): Define\Query\Create
|
||||||
|
{
|
||||||
|
if (is_array($create_definitions)) {
|
||||||
|
foreach ($create_definitions as $definition) {
|
||||||
|
$this->addDefinition($definition);
|
||||||
|
}
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
return $this->addDefinition($create_definitions);
|
||||||
|
}
|
||||||
|
public function options(array|string $table_options): Define\Query\Create
|
||||||
|
{
|
||||||
|
if (is_string($table_options)) {
|
||||||
|
return $this->addOption($table_options);
|
||||||
|
}
|
||||||
|
foreach ($table_options as $option) {
|
||||||
|
$this->addOption($option);
|
||||||
|
}
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
public function partition(array|string $partition_options): Define\Query\Create
|
||||||
|
{
|
||||||
|
if (is_string($partition_options)) {
|
||||||
|
return $this->addPartition($partition_options);
|
||||||
|
}
|
||||||
|
foreach ($partition_options as $option) {
|
||||||
|
$this->addPartition($option);
|
||||||
|
}
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
public function build(): string
|
||||||
|
{
|
||||||
|
$query = [
|
||||||
|
"CREATE TABLE {$this->name}",
|
||||||
|
$this->getDefinitions(),
|
||||||
|
$this->getOptions(),
|
||||||
|
$this->getPartitions()
|
||||||
|
];
|
||||||
|
return implode('', $query);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function addDefinition(string $definition): Create
|
||||||
|
{
|
||||||
|
if (!isset($this->definitions)) {
|
||||||
|
$this->definitions = [];
|
||||||
|
}
|
||||||
|
$this->definitions []= $definition;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
protected function addOption(string $option): Create
|
||||||
|
{
|
||||||
|
if (!isset($this->options)) {
|
||||||
|
$this->options = [];
|
||||||
|
}
|
||||||
|
$this->options []= $option;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
protected function addPartition(string $partition): Create
|
||||||
|
{
|
||||||
|
if (!isset($this->partitions)) {
|
||||||
|
$this->partitions = [];
|
||||||
|
}
|
||||||
|
$this->partitions []= $partition;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
protected function getDefinitions(): string
|
||||||
|
{
|
||||||
|
return ' (' . implode(', ', $this->definitions) . ')';
|
||||||
|
}
|
||||||
|
protected function getOptions(): string
|
||||||
|
{
|
||||||
|
if (!isset($this->options) or count($this->options) <= 0) {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
return ' ' . implode(' ', $this->options);
|
||||||
|
}
|
||||||
|
protected function getPartitions(): string
|
||||||
|
{
|
||||||
|
if (!isset($this->partitions) or count($this->partitions) <= 0) {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
return ' PARTITION BY (' . implode(', ', $this->partitions) . ')';
|
||||||
|
}
|
||||||
|
}
|
104
app/common/Implement/Database/Query/Create/Definition.php
Normal file
104
app/common/Implement/Database/Query/Create/Definition.php
Normal file
@ -0,0 +1,104 @@
|
|||||||
|
<?php
|
||||||
|
namespace ProVM\Implement\Data\Query\Create;
|
||||||
|
|
||||||
|
use ProVM\Define\Query\Create\CreateDefinition;
|
||||||
|
|
||||||
|
class Definition implements CreateDefinition
|
||||||
|
{
|
||||||
|
protected string $name;
|
||||||
|
protected string $type;
|
||||||
|
protected int $size;
|
||||||
|
protected bool $primary;
|
||||||
|
protected bool $auto_increment;
|
||||||
|
protected bool $unsigned;
|
||||||
|
protected mixed $default;
|
||||||
|
protected string $foreign_table;
|
||||||
|
protected string $foreign_key;
|
||||||
|
protected int $foreign_delete;
|
||||||
|
protected int $foreign_update;
|
||||||
|
|
||||||
|
public function name(string $name): CreateDefinition
|
||||||
|
{
|
||||||
|
$this->name = $name;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
public function type(string $type, ?int $size = null): CreateDefinition
|
||||||
|
{
|
||||||
|
$this->type = $type;
|
||||||
|
if ($size !== null) {
|
||||||
|
$this->size = $size;
|
||||||
|
}
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
public function primary(): CreateDefinition
|
||||||
|
{
|
||||||
|
$this->primary = true;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
public function autoIncrement(): CreateDefinition
|
||||||
|
{
|
||||||
|
$this->auto_increment = true;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
public function unsigned(): CreateDefinition
|
||||||
|
{
|
||||||
|
$this->unsigned = true;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
public function default(mixed $value): CreateDefinition
|
||||||
|
{
|
||||||
|
$this->default = $value;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
public function foreign(string $reference_table, string $reference_column = 'id', int $on_delete = CreateDefinition::CASCADE, int $on_update = CreateDefinition::CASCADE): CreateDefinition
|
||||||
|
{
|
||||||
|
$this->foreign_table = $reference_table;
|
||||||
|
$this->foreign_key = $reference_column;
|
||||||
|
$this->foreign_delete = $on_delete;
|
||||||
|
$this->foreign_update = $on_update;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function __toString(): string
|
||||||
|
{
|
||||||
|
$type = $this->type ?? 'int';
|
||||||
|
if (isset($this->size)) {
|
||||||
|
$type = "{$type}({$this->size})";
|
||||||
|
} elseif (in_array($type, ['varchar'])) {
|
||||||
|
$type = "{$type}(255)";
|
||||||
|
}
|
||||||
|
$output = [
|
||||||
|
"`{$this->name}`",
|
||||||
|
$type
|
||||||
|
];
|
||||||
|
if (isset($this->unsigned)) {
|
||||||
|
$output []= 'UNSIGNED';
|
||||||
|
}
|
||||||
|
if (isset($this->default)) {
|
||||||
|
$default = $this->default;
|
||||||
|
if (in_array($this->type, ['varchar', 'text', 'char'])) {
|
||||||
|
$default = "'{$default}'";
|
||||||
|
}
|
||||||
|
$output []= "DEFAULT {$default}";
|
||||||
|
}
|
||||||
|
if (isset($this->auto_increment)) {
|
||||||
|
$output []= 'AUTO_INCREMENT';
|
||||||
|
}
|
||||||
|
if (isset($this->primary)) {
|
||||||
|
$output []= 'PRIMARY KEY';
|
||||||
|
}
|
||||||
|
if (isset($this->foreign_table)) {
|
||||||
|
$output []= "REFERENCES `{$this->foreign_table}` (`{$this->foreign_key}`)";
|
||||||
|
$on = [
|
||||||
|
'RESTRICT',
|
||||||
|
'CASCADE',
|
||||||
|
'SET_NULL',
|
||||||
|
'NO_ACTION',
|
||||||
|
'SET_DEFAULT'
|
||||||
|
];
|
||||||
|
$output []= "ON DELETE {$on[$this->foreign_delete]}";
|
||||||
|
$output []= "ON UPDATE {$on[$this->foreign_update]}";
|
||||||
|
}
|
||||||
|
return implode(' ', $output);
|
||||||
|
}
|
||||||
|
}
|
89
app/common/Implement/Database/Query/Delete.php
Normal file
89
app/common/Implement/Database/Query/Delete.php
Normal file
@ -0,0 +1,89 @@
|
|||||||
|
<?php
|
||||||
|
namespace Incoviba\Common\Implement\Database\Query;
|
||||||
|
|
||||||
|
use Incoviba\Common\Define;
|
||||||
|
use Incoviba\Common\Ideal;
|
||||||
|
|
||||||
|
class Delete extends Ideal\Query implements Define\Query\Delete
|
||||||
|
{
|
||||||
|
protected string $table;
|
||||||
|
protected array $conditions;
|
||||||
|
protected array $sorts;
|
||||||
|
protected int $limit;
|
||||||
|
|
||||||
|
public function from(string $table): Delete
|
||||||
|
{
|
||||||
|
$this->table = $table;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
public function where(array|string $conditions): Delete
|
||||||
|
{
|
||||||
|
if (is_string($conditions)) {
|
||||||
|
return $this->addCondition($conditions);
|
||||||
|
}
|
||||||
|
foreach ($conditions as $condition) {
|
||||||
|
$this->addCondition($condition);
|
||||||
|
}
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
public function order(array|string $sorting): Delete
|
||||||
|
{
|
||||||
|
if (is_string($sorting)) {
|
||||||
|
return $this->addOrder($sorting);
|
||||||
|
}
|
||||||
|
foreach ($sorting as $order) {
|
||||||
|
$this->addOrder($order);
|
||||||
|
}
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
public function limit(int $limit): Delete
|
||||||
|
{
|
||||||
|
$this->limit = $limit;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
public function build(): string
|
||||||
|
{
|
||||||
|
$query = [
|
||||||
|
"DELETE FROM {$this->table}",
|
||||||
|
$this->getConditions(),
|
||||||
|
$this->getSorting(),
|
||||||
|
$this->getLimit()
|
||||||
|
];
|
||||||
|
return implode('', $query);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function addCondition(string $condition): Delete
|
||||||
|
{
|
||||||
|
if (!isset($this->conditions)) {
|
||||||
|
$this->conditions = [];
|
||||||
|
}
|
||||||
|
$this->conditions []= $condition;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
protected function getConditions(): string
|
||||||
|
{
|
||||||
|
return ' WHERE ' . implode(' AND ', $this->conditions);
|
||||||
|
}
|
||||||
|
protected function addOrder(string $order): Delete
|
||||||
|
{
|
||||||
|
if (!isset($this->sorts)) {
|
||||||
|
$this->sorts = [];
|
||||||
|
}
|
||||||
|
$this->sorts []= $order;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
protected function getSorting(): string
|
||||||
|
{
|
||||||
|
if (!isset($this->sorts) or count($this->sorts) === 0) {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
return ' ORDER BY ' . implode(', ', $this->sorts);
|
||||||
|
}
|
||||||
|
protected function getLimit(): string
|
||||||
|
{
|
||||||
|
if (!isset($this->limit) or $this->limit <= 0) {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
return " LIMIT {$this->limit}";
|
||||||
|
}
|
||||||
|
}
|
87
app/common/Implement/Database/Query/Insert.php
Normal file
87
app/common/Implement/Database/Query/Insert.php
Normal file
@ -0,0 +1,87 @@
|
|||||||
|
<?php
|
||||||
|
namespace Incoviba\Common\Implement\Database\Query;
|
||||||
|
|
||||||
|
use Incoviba\Common\Define;
|
||||||
|
use Incoviba\Common\Ideal;
|
||||||
|
|
||||||
|
class Insert extends Ideal\Query implements Define\Query\Insert
|
||||||
|
{
|
||||||
|
protected string $table;
|
||||||
|
protected array $columns;
|
||||||
|
protected array $values;
|
||||||
|
protected Define\Query\Select $select;
|
||||||
|
|
||||||
|
public function into(string $table, ?array $columns = null): Insert
|
||||||
|
{
|
||||||
|
$this->table = $table;
|
||||||
|
if ($columns !== null) {
|
||||||
|
return $this->columns($columns);
|
||||||
|
}
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
public function columns(array $columns): Insert
|
||||||
|
{
|
||||||
|
foreach ($columns as $column) {
|
||||||
|
$this->addColumn($column);
|
||||||
|
}
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
public function values(array $values): Insert
|
||||||
|
{
|
||||||
|
foreach ($values as $value) {
|
||||||
|
$this->addValue($value);
|
||||||
|
}
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
public function select(Define\Query\Select $select): Insert
|
||||||
|
{
|
||||||
|
$this->select = $select;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
public function build(): string
|
||||||
|
{
|
||||||
|
$query = [
|
||||||
|
"INSERT INTO {$this->table}"
|
||||||
|
];
|
||||||
|
if (isset($this->select)) {
|
||||||
|
$query []= " {$this->select}";
|
||||||
|
return implode('', $query);
|
||||||
|
}
|
||||||
|
$query []= $this->getColumns();
|
||||||
|
$query []= $this->getValues();
|
||||||
|
return implode('', $query);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function addColumn(string $column): Insert
|
||||||
|
{
|
||||||
|
if (!isset($this->columns)) {
|
||||||
|
$this->columns = [];
|
||||||
|
}
|
||||||
|
$this->columns []= $column;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
protected function addValue(mixed $value): Insert
|
||||||
|
{
|
||||||
|
if (!isset($this->values)) {
|
||||||
|
$this->values = [];
|
||||||
|
}
|
||||||
|
$this->values []= $value;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
protected function getColumns(): string
|
||||||
|
{
|
||||||
|
return ' (' . implode(', ', array_map(function(string $column) {return "`{$column}`";}, $this->columns)) . ')';
|
||||||
|
}
|
||||||
|
protected function getValues(): string
|
||||||
|
{
|
||||||
|
return ' VALUES (' . implode(', ', array_map(function($value) {
|
||||||
|
if ($value === '?') {
|
||||||
|
return $value;
|
||||||
|
}
|
||||||
|
if ($value === (int) $value) {
|
||||||
|
return $value;
|
||||||
|
}
|
||||||
|
return "'{$value}'";
|
||||||
|
}, $this->values)) . ')';
|
||||||
|
}
|
||||||
|
}
|
215
app/common/Implement/Database/Query/Select.php
Normal file
215
app/common/Implement/Database/Query/Select.php
Normal file
@ -0,0 +1,215 @@
|
|||||||
|
<?php
|
||||||
|
namespace Incoviba\Common\Implement\Database\Query;
|
||||||
|
|
||||||
|
use Incoviba\Common\Define;
|
||||||
|
use Incoviba\Common\Ideal;
|
||||||
|
|
||||||
|
class Select extends Ideal\Query implements Define\Query\Select
|
||||||
|
{
|
||||||
|
protected array $columns;
|
||||||
|
protected string $table;
|
||||||
|
protected array $joins;
|
||||||
|
protected array $conditions;
|
||||||
|
protected array $groups;
|
||||||
|
protected array $haves;
|
||||||
|
protected array $orders;
|
||||||
|
protected int $limit;
|
||||||
|
protected int $offset;
|
||||||
|
|
||||||
|
public function columns(array|string $expressions): Select
|
||||||
|
{
|
||||||
|
if (is_string($expressions)) {
|
||||||
|
return $this->addColumn($expressions);
|
||||||
|
}
|
||||||
|
foreach ($expressions as $expression) {
|
||||||
|
$this->addColumn($expression);
|
||||||
|
}
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
public function from(string $table): Select
|
||||||
|
{
|
||||||
|
$this->table = $table;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
public function joined(array|string $joins): Select
|
||||||
|
{
|
||||||
|
if (is_string($joins)) {
|
||||||
|
return $this->addJoin($joins);
|
||||||
|
}
|
||||||
|
foreach ($joins as $join) {
|
||||||
|
$this->addJoin($join);
|
||||||
|
}
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
public function where(array|string $conditions): Select
|
||||||
|
{
|
||||||
|
if (is_string($conditions)) {
|
||||||
|
return $this->addCondition($conditions);
|
||||||
|
}
|
||||||
|
foreach ($conditions as $condition) {
|
||||||
|
$this->addCondition($condition);
|
||||||
|
}
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
public function group(array|string $grouping): Select
|
||||||
|
{
|
||||||
|
if (is_string($grouping)) {
|
||||||
|
return $this->addGroup($grouping);
|
||||||
|
}
|
||||||
|
foreach ($grouping as $group) {
|
||||||
|
$this->addGroup($group);
|
||||||
|
}
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
public function having(array|string $conditions): Select
|
||||||
|
{
|
||||||
|
if (is_string($conditions)) {
|
||||||
|
return $this->addCondition($conditions);
|
||||||
|
}
|
||||||
|
foreach ($conditions as $condition) {
|
||||||
|
$this->addCondition($condition);
|
||||||
|
}
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
public function order(array|string $sorting): Select
|
||||||
|
{
|
||||||
|
if (is_string($sorting)) {
|
||||||
|
return $this->addOrder($sorting);
|
||||||
|
}
|
||||||
|
foreach ($sorting as $order) {
|
||||||
|
$this->addOrder($order);
|
||||||
|
}
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
public function limit(int $limit, ?int $offset = null): Select
|
||||||
|
{
|
||||||
|
$this->limit = $limit;
|
||||||
|
if ($offset !== null) {
|
||||||
|
return $this->offset($offset);
|
||||||
|
}
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
public function offset(int $offset): Select
|
||||||
|
{
|
||||||
|
$this->offset = $offset;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
public function build(): string
|
||||||
|
{
|
||||||
|
$query = [
|
||||||
|
"SELECT {$this->getColumns()} FROM {$this->table}",
|
||||||
|
$this->getJoins(),
|
||||||
|
$this->getConditions(),
|
||||||
|
$this->getGroups(),
|
||||||
|
$this->getHaving(),
|
||||||
|
$this->getOrder(),
|
||||||
|
$this->getLimit()
|
||||||
|
];
|
||||||
|
return implode('', $query);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function addColumn(string $expression): Select
|
||||||
|
{
|
||||||
|
if (!isset($this->columns)) {
|
||||||
|
$this->columns = [];
|
||||||
|
}
|
||||||
|
$this->columns []= $expression;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
protected function addJoin(string $join): Select
|
||||||
|
{
|
||||||
|
if (!isset($this->joins)) {
|
||||||
|
$this->joins = [];
|
||||||
|
}
|
||||||
|
$this->joins []= $join;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
protected function addCondition(string $condition): Select
|
||||||
|
{
|
||||||
|
if (!isset($this->coditions)) {
|
||||||
|
$this->conditions = [];
|
||||||
|
}
|
||||||
|
$this->conditions []= $condition;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
protected function addGroup(string $group): Select
|
||||||
|
{
|
||||||
|
if (!isset($this->groups)) {
|
||||||
|
$this->groups = [];
|
||||||
|
}
|
||||||
|
$this->groups []= $group;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
protected function addHaving(string $having): Select
|
||||||
|
{
|
||||||
|
if (!isset($this->haves)) {
|
||||||
|
$this->haves = [];
|
||||||
|
}
|
||||||
|
$this->haves []= $having;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
protected function addOrder(string $order): Select
|
||||||
|
{
|
||||||
|
if (!isset($this->orders)) {
|
||||||
|
$this->orders = [];
|
||||||
|
}
|
||||||
|
$this->orders []= $order;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
protected function getColumns(): string
|
||||||
|
{
|
||||||
|
if (!isset($this->columns) or count($this->columns) === 0) {
|
||||||
|
return '*';
|
||||||
|
}
|
||||||
|
return implode(', ', $this->columns);
|
||||||
|
}
|
||||||
|
protected function getJoins(): string
|
||||||
|
{
|
||||||
|
if (!isset($this->joins) or count($this->joins) === 0) {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
return ' ' . implode(' ', $this->joins);
|
||||||
|
}
|
||||||
|
protected function getConditions(): string
|
||||||
|
{
|
||||||
|
if (!isset($this->conditions) or count($this->conditions) === 0) {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
return ' WHERE ' . implode(' AND ', $this->conditions);
|
||||||
|
}
|
||||||
|
protected function getGroups(): string
|
||||||
|
{
|
||||||
|
if (!isset($this->groups) or count($this->groups) === 0) {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
return ' GROUP BY ' . implode(', ', $this->groups);
|
||||||
|
}
|
||||||
|
protected function getHaving(): string
|
||||||
|
{
|
||||||
|
if (!isset($this->haves) or count($this->haves) === 0) {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
return ' HAVING ' . implode(' AND ', $this->haves);
|
||||||
|
}
|
||||||
|
protected function getOrder(): string
|
||||||
|
{
|
||||||
|
if (!isset($this->orders) or count($this->orders) === 0) {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
return ' ORDER BY ' . implode(', ', $this->orders);
|
||||||
|
}
|
||||||
|
protected function getLimit(): string
|
||||||
|
{
|
||||||
|
if (!isset($this->limit) or $this->limit <= 0) {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
return " LIMIT {$this->limit}{$this->getOffset()}";
|
||||||
|
}
|
||||||
|
protected function getOffset(): string
|
||||||
|
{
|
||||||
|
if (!isset($this->offset) or $this->offset <= 0) {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
return " OFFSET {$this->offset}";
|
||||||
|
}
|
||||||
|
}
|
113
app/common/Implement/Database/Query/Update.php
Normal file
113
app/common/Implement/Database/Query/Update.php
Normal file
@ -0,0 +1,113 @@
|
|||||||
|
<?php
|
||||||
|
namespace Incoviba\Common\Implement\Database\Query;
|
||||||
|
|
||||||
|
use Incoviba\Common\Define;
|
||||||
|
use Incoviba\Common\Ideal;
|
||||||
|
|
||||||
|
class Update extends Ideal\Query implements Define\Query\Update
|
||||||
|
{
|
||||||
|
protected string $table;
|
||||||
|
protected array $setPairs;
|
||||||
|
protected array $conditions;
|
||||||
|
protected array $orders;
|
||||||
|
protected int $limit;
|
||||||
|
|
||||||
|
public function table(string $table): Define\Query\Update
|
||||||
|
{
|
||||||
|
$this->table = $table;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
public function set(array|string $column_pairs): Define\Query\Update
|
||||||
|
{
|
||||||
|
if (is_string($column_pairs)) {
|
||||||
|
return $this->addSet($column_pairs);
|
||||||
|
}
|
||||||
|
foreach ($column_pairs as $pair) {
|
||||||
|
$this->addSet($pair);
|
||||||
|
}
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
public function where(array|string $conditions): Define\Query\Update
|
||||||
|
{
|
||||||
|
if (is_string($conditions)) {
|
||||||
|
return $this->addCondition($conditions);
|
||||||
|
}
|
||||||
|
foreach ($conditions as $condition) {
|
||||||
|
$this->addCondition($condition);
|
||||||
|
}
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
public function order(array|string $ordering): Define\Query\Update
|
||||||
|
{
|
||||||
|
if (is_string($ordering)) {
|
||||||
|
return $this->addOrder($ordering);
|
||||||
|
}
|
||||||
|
foreach ($ordering as $order) {
|
||||||
|
$this->addOrder($order);
|
||||||
|
}
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
public function limit(int $limit): Define\Query\Update
|
||||||
|
{
|
||||||
|
$this->limit = $limit;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
public function build(): string
|
||||||
|
{
|
||||||
|
$query = [
|
||||||
|
"UPDATE {$this->table}",
|
||||||
|
$this->getSet(),
|
||||||
|
$this->getConditions(),
|
||||||
|
$this->getOrder(),
|
||||||
|
$this->getLimit()
|
||||||
|
];
|
||||||
|
return implode('', $query);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function addSet(string $pair): Update
|
||||||
|
{
|
||||||
|
if (!isset($this->setPairs)) {
|
||||||
|
$this->setPairs = [];
|
||||||
|
}
|
||||||
|
$this->setPairs []= $pair;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
protected function addCondition(string $condition): Update
|
||||||
|
{
|
||||||
|
if (!isset($this->conditions)) {
|
||||||
|
$this->conditions = [];
|
||||||
|
}
|
||||||
|
$this->conditions []= $condition;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
protected function addOrder(string $order): Update
|
||||||
|
{
|
||||||
|
if (!isset($this->orders)) {
|
||||||
|
$this->orders = [];
|
||||||
|
}
|
||||||
|
$this->orders []= $order;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
protected function getSet(): string
|
||||||
|
{
|
||||||
|
return ' SET ' . implode(', ', $this->setPairs);
|
||||||
|
}
|
||||||
|
protected function getConditions(): string
|
||||||
|
{
|
||||||
|
return ' WHERE ' . implode(' AND ', $this->conditions);
|
||||||
|
}
|
||||||
|
protected function getOrder(): string
|
||||||
|
{
|
||||||
|
if (!isset($this->orders) or count($this->orders) === 0) {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
return ' ORDER BY ' . implode(', ', $this->orders);
|
||||||
|
}
|
||||||
|
protected function getLimit(): string
|
||||||
|
{
|
||||||
|
if (!isset($this->limit) or $this->limit <= 0) {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
return " LIMIT {$this->limit}";
|
||||||
|
}
|
||||||
|
}
|
7
app/resources/routes/api/money.php
Normal file
7
app/resources/routes/api/money.php
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
<?php
|
||||||
|
use Incoviba\Controller\API\Money;
|
||||||
|
|
||||||
|
$app->group('/money', function($app) {
|
||||||
|
$app->post('/ipc[/]', [Money::class, 'ipc']);
|
||||||
|
$app->post('[/]', [Money::class, 'get']);
|
||||||
|
});
|
@ -22,6 +22,7 @@ $app->group('/ventas', function($app) {
|
|||||||
$app->post('[/]', [Ventas::class, 'proyecto']);
|
$app->post('[/]', [Ventas::class, 'proyecto']);
|
||||||
});
|
});
|
||||||
$app->group('/venta/{venta_id}', function($app) {
|
$app->group('/venta/{venta_id}', function($app) {
|
||||||
|
$app->get('/unidades', [Ventas::class, 'unidades']);
|
||||||
$app->get('/comentarios', [Ventas::class, 'comentarios']);
|
$app->get('/comentarios', [Ventas::class, 'comentarios']);
|
||||||
$app->get('[/]', [Ventas::class, 'get']);
|
$app->get('[/]', [Ventas::class, 'get']);
|
||||||
});
|
});
|
||||||
|
6
app/resources/routes/api/ventas/facturacion.php
Normal file
6
app/resources/routes/api/ventas/facturacion.php
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
<?php
|
||||||
|
use Incoviba\Controller\API\Ventas\Facturacion;
|
||||||
|
|
||||||
|
$app->group('/facturacion', function($app) {
|
||||||
|
$app->get('/proyecto/{proyecto_id}[/]', [Facturacion::class, 'proyecto']);
|
||||||
|
});
|
6
app/resources/routes/ventas/facturacion.php
Normal file
6
app/resources/routes/ventas/facturacion.php
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
<?php
|
||||||
|
use Incoviba\Controller\Ventas\Facturacion;
|
||||||
|
|
||||||
|
$app->group('/facturacion', function($app) {
|
||||||
|
$app->get('[/]', Facturacion::class);
|
||||||
|
});
|
@ -224,6 +224,7 @@
|
|||||||
const proyecto_id = element.data('proyecto')
|
const proyecto_id = element.data('proyecto')
|
||||||
this.get().tipos(proyecto_id)
|
this.get().tipos(proyecto_id)
|
||||||
})
|
})
|
||||||
|
$('#data').hide()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
$(document).ready(() => {
|
$(document).ready(() => {
|
||||||
|
384
app/resources/views/ventas/facturacion.blade.php
Normal file
384
app/resources/views/ventas/facturacion.blade.php
Normal file
@ -0,0 +1,384 @@
|
|||||||
|
@extends('layout.base')
|
||||||
|
|
||||||
|
@section('page_content')
|
||||||
|
<div class="ui container">
|
||||||
|
<h2 class="ui header">Matriz Facturación</h2>
|
||||||
|
<h4 class="ui dividing header">
|
||||||
|
<div class="ui two column grid">
|
||||||
|
<div id="list_title" class="column">Proyectos</div>
|
||||||
|
<div class="right aligned column">
|
||||||
|
<div class="ui tiny icon buttons">
|
||||||
|
<button id="up_button" class="ui button">
|
||||||
|
<i class="up arrow icon"></i>
|
||||||
|
</button>
|
||||||
|
<button id="refresh_button" class="ui button">
|
||||||
|
<i class="refresh icon"></i>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</h4>
|
||||||
|
<div id="proyectos" class="ui link selection list">
|
||||||
|
@foreach ($proyectos as $proyecto)
|
||||||
|
<div class="item" data-proyecto="{{$proyecto->id}}">{{$proyecto->descripcion}}</div>
|
||||||
|
@endforeach
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<table class="ui table" id="data"></table>
|
||||||
|
@endsection
|
||||||
|
|
||||||
|
@include('layout.head.styles.datatables')
|
||||||
|
@include('layout.body.scripts.datatables')
|
||||||
|
|
||||||
|
@push('page_scripts')
|
||||||
|
<script>
|
||||||
|
const money = {
|
||||||
|
ufs: {},
|
||||||
|
ipcs: {},
|
||||||
|
sent: {
|
||||||
|
uf: {},
|
||||||
|
ipc: {}
|
||||||
|
},
|
||||||
|
get() {
|
||||||
|
return {
|
||||||
|
uf: date => {
|
||||||
|
if (typeof this.sent.uf[date.toISOString()] !== 'undefined') {
|
||||||
|
return this.sent.uf[date.toISOString()]
|
||||||
|
}
|
||||||
|
const url = '{{$urls->api}}/money'
|
||||||
|
const data = new FormData()
|
||||||
|
data.set('provider', 'uf')
|
||||||
|
data.set('fecha', date.toISOString())
|
||||||
|
const options = {
|
||||||
|
method: 'post',
|
||||||
|
body: data
|
||||||
|
}
|
||||||
|
return this.sent.uf[date.toISOString()] = fetch(url, options).then(response => {
|
||||||
|
if (response.ok) {
|
||||||
|
return response.json()
|
||||||
|
}
|
||||||
|
}).then(json => {
|
||||||
|
return this.ufs[json.input.fecha] = json.uf
|
||||||
|
})
|
||||||
|
},
|
||||||
|
ipc: (end, start) => {
|
||||||
|
const dateKey = [start.getFullYear(), (start.getMonth()+1), end.getFullYear(), (end.getMonth()+1)].join('-')
|
||||||
|
if (typeof this.sent.ipc[dateKey] !== 'undefined') {
|
||||||
|
return this.sent.ipc[dateKey]
|
||||||
|
}
|
||||||
|
const url = '{{$urls->api}}/money/ipc'
|
||||||
|
const data = new FormData()
|
||||||
|
data.set('provider', 'ipc')
|
||||||
|
data.set('start', start.toISOString())
|
||||||
|
data.set('end', end.toISOString())
|
||||||
|
const options = {
|
||||||
|
method: 'post',
|
||||||
|
body: data
|
||||||
|
}
|
||||||
|
return this.sent.ipc[dateKey] = fetch(url, options).then(response => {
|
||||||
|
if (response.ok) {
|
||||||
|
return response.json()
|
||||||
|
}
|
||||||
|
}).then(json => {
|
||||||
|
return this.ipcs[json.date_string] = json.ipc
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class Unidad {
|
||||||
|
id
|
||||||
|
tipo
|
||||||
|
descripcion
|
||||||
|
prorrateo
|
||||||
|
precio
|
||||||
|
|
||||||
|
constructor({id, tipo, descripcion, prorrateo, precio})
|
||||||
|
{
|
||||||
|
this.id = id
|
||||||
|
this.tipo = tipo
|
||||||
|
this.descripcion = descripcion
|
||||||
|
this.prorrateo = prorrateo
|
||||||
|
this.precio = precio
|
||||||
|
}
|
||||||
|
}
|
||||||
|
class Venta {
|
||||||
|
id
|
||||||
|
precio
|
||||||
|
fecha
|
||||||
|
escritura
|
||||||
|
uf
|
||||||
|
ipc
|
||||||
|
unidades
|
||||||
|
principal
|
||||||
|
|
||||||
|
constructor({id, precio, fecha, escritura}) {
|
||||||
|
this.id = id
|
||||||
|
this.precio = precio
|
||||||
|
this.fecha = fecha
|
||||||
|
this.escritura = escritura
|
||||||
|
this.uf = 1
|
||||||
|
this.ipc = 1
|
||||||
|
this.unidades = []
|
||||||
|
}
|
||||||
|
|
||||||
|
get() {
|
||||||
|
return {
|
||||||
|
unidades: () => {
|
||||||
|
const url = '{{$urls->api}}/venta/' + this.id + '/unidades'
|
||||||
|
return fetch(url).then(response => {
|
||||||
|
if (response.ok) {
|
||||||
|
return response.json()
|
||||||
|
}
|
||||||
|
}).then(json => {
|
||||||
|
json.unidades.forEach(unidad => {
|
||||||
|
const tipo = unidad.proyecto_tipo_unidad.tipo_unidad.descripcion
|
||||||
|
const data = {
|
||||||
|
id: unidad.id,
|
||||||
|
tipo: tipo.charAt(0).toUpperCase() + tipo.slice(1),
|
||||||
|
descripcion: unidad.descripcion,
|
||||||
|
prorrateo: unidad.prorrateo,
|
||||||
|
precio: 0
|
||||||
|
}
|
||||||
|
if (unidad.current_precio !== null) {
|
||||||
|
data.precio = unidad.current_precio.valor
|
||||||
|
}
|
||||||
|
const u = new Unidad(data)
|
||||||
|
this.unidades.push(u)
|
||||||
|
})
|
||||||
|
this.principal = this.unidades.filter(unidad => unidad.tipo === 'Departamento')[0]
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
draw({tbody, valor_terreno}) {
|
||||||
|
/**
|
||||||
|
'Venta',
|
||||||
|
'Unidades',
|
||||||
|
'Tipo',
|
||||||
|
'Unidad',
|
||||||
|
'Fecha Promesa',
|
||||||
|
'Valor Promesa',
|
||||||
|
'Prorrateo',
|
||||||
|
'Descuento',
|
||||||
|
'Precio Venta',
|
||||||
|
'Precio Bruto',
|
||||||
|
'IVA',
|
||||||
|
'Precio Neto',
|
||||||
|
'% IVA/Neto',
|
||||||
|
'Fecha Escritura',
|
||||||
|
'UF',
|
||||||
|
'IPC'
|
||||||
|
*/
|
||||||
|
const dateFormatter = new Intl.DateTimeFormat('es-CL', {year: 'numeric', month: 'numeric', day: 'numeric'})
|
||||||
|
const pesosFormatter = new Intl.NumberFormat('es-CL', {style: 'currency', currency: 'CLP'})
|
||||||
|
const ufFormatter = new Intl.NumberFormat('es-CL', {minimumFractionDigits: 2, maximumFractionDigits: 2})
|
||||||
|
const venta = this.unidades[0].descripcion
|
||||||
|
const cantidad = this.unidades.length
|
||||||
|
this.unidades.forEach(unidad => {
|
||||||
|
const values = [
|
||||||
|
venta,
|
||||||
|
cantidad,
|
||||||
|
unidad.tipo,
|
||||||
|
unidad.descripcion,
|
||||||
|
dateFormatter.format(this.fecha),
|
||||||
|
ufFormatter.format(unidad.precio) + ' UF',
|
||||||
|
unidad.prorrateo,
|
||||||
|
'',
|
||||||
|
'',
|
||||||
|
'',
|
||||||
|
'',
|
||||||
|
'',
|
||||||
|
'',
|
||||||
|
'',
|
||||||
|
'',
|
||||||
|
''
|
||||||
|
]
|
||||||
|
if (this.escritura !== null) {
|
||||||
|
const descuento = valor_terreno * (1 + this.ipc / 100) * unidad.prorrateo
|
||||||
|
const precio_venta = unidad.precio * this.uf
|
||||||
|
const precio_bruto = precio_venta - descuento
|
||||||
|
const precio_neto = precio_bruto / 1.19
|
||||||
|
const iva = precio_bruto - precio_neto
|
||||||
|
|
||||||
|
let i = 7
|
||||||
|
values[i++] = pesosFormatter.format(descuento)
|
||||||
|
values[i++] = pesosFormatter.format(precio_venta)
|
||||||
|
values[i++] = pesosFormatter.format(precio_bruto)
|
||||||
|
values[i++] = pesosFormatter.format(iva)
|
||||||
|
values[i++] = pesosFormatter.format(precio_neto)
|
||||||
|
values[i++] = (iva / precio_venta * 100).toFixed(2) + '%'
|
||||||
|
values[i++] = dateFormatter.format(this.escritura)
|
||||||
|
values[i++] = ufFormatter.format(this.uf)
|
||||||
|
values[i++] = (this.ipc).toFixed(2) + '%'
|
||||||
|
}
|
||||||
|
const row = $('<tr></tr>')
|
||||||
|
values.forEach(value => {
|
||||||
|
row.append(
|
||||||
|
$('<td></td>').html(value)
|
||||||
|
)
|
||||||
|
})
|
||||||
|
tbody.append(row)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const proyectos = {
|
||||||
|
ids: {},
|
||||||
|
selected: 0,
|
||||||
|
data: JSON.parse('{!! json_encode($proyectos) !!}'),
|
||||||
|
table: null,
|
||||||
|
get: function() {
|
||||||
|
return {
|
||||||
|
ventas: () => {
|
||||||
|
const url = '{{$urls->api}}/ventas/facturacion/proyecto/' + this.selected
|
||||||
|
return fetch(url).then(response => {
|
||||||
|
if (response.ok) {
|
||||||
|
return response.json()
|
||||||
|
}
|
||||||
|
}).then(json => {
|
||||||
|
const idx = this.data.findIndex(proyecto => proyecto.id === json.proyecto_id)
|
||||||
|
const fecha_terreno = new Date(this.data[idx].terreno.date)
|
||||||
|
this.data[idx]['ventas'] = []
|
||||||
|
const ventas = []
|
||||||
|
json.ventas.forEach(venta => {
|
||||||
|
const data = {
|
||||||
|
id: venta.id,
|
||||||
|
precio: venta.valor,
|
||||||
|
fecha: new Date(venta.fecha),
|
||||||
|
escritura: null
|
||||||
|
}
|
||||||
|
if (['escriturando'].includes(venta.current_estado.tipo_estado_venta.descripcion)) {
|
||||||
|
data.escritura = new Date(venta.current_estado.fecha)
|
||||||
|
}
|
||||||
|
const v = new Venta(data)
|
||||||
|
const promises = []
|
||||||
|
if (v.escritura !== null) {
|
||||||
|
promises.push(money.get().uf(v.escritura).then(uf => {
|
||||||
|
v.uf = uf
|
||||||
|
}))
|
||||||
|
promises.push(money.get().ipc(v.escritura, fecha_terreno).then(ipc => {
|
||||||
|
v.ipc = ipc
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
promises.push(v.get().unidades())
|
||||||
|
const promise = Promise.all(promises).then(() => {
|
||||||
|
this.data[idx].ventas.push(v)
|
||||||
|
})
|
||||||
|
ventas.push(promise)
|
||||||
|
})
|
||||||
|
Promise.all(ventas).then(() => {
|
||||||
|
this.data[idx].ventas.sort((a, b) => parseInt(a.principal.descripcion) - parseInt(b.principal.descripcion))
|
||||||
|
this.draw().ventas(idx)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
draw: function() {
|
||||||
|
return {
|
||||||
|
proyectos: () => {
|
||||||
|
if (this.table !== null) {
|
||||||
|
this.table.clear()
|
||||||
|
}
|
||||||
|
$(this.ids.data).hide()
|
||||||
|
$(this.ids.proyectos).show()
|
||||||
|
},
|
||||||
|
ventas: proyecto_idx => {
|
||||||
|
const table = $(this.ids.data)
|
||||||
|
if (this.table !== null) {
|
||||||
|
this.table.clear().destroy()
|
||||||
|
}
|
||||||
|
table.append(this.draw().thead())
|
||||||
|
table.append(this.draw().tbody(proyecto_idx))
|
||||||
|
table.show()
|
||||||
|
$(this.ids.proyectos).hide()
|
||||||
|
if (this.table === null) {
|
||||||
|
this.table = table.DataTable()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
thead: () => {
|
||||||
|
const thead = $('<thead></thead>')
|
||||||
|
const columns = [
|
||||||
|
'Venta',
|
||||||
|
'Unidades',
|
||||||
|
'Tipo',
|
||||||
|
'Unidad',
|
||||||
|
'Fecha Promesa',
|
||||||
|
'Valor Promesa',
|
||||||
|
'Prorrateo',
|
||||||
|
'Descuento',
|
||||||
|
'Precio Venta',
|
||||||
|
'Precio Bruto',
|
||||||
|
'IVA',
|
||||||
|
'Precio Neto',
|
||||||
|
'% IVA/Neto',
|
||||||
|
'Fecha Escritura',
|
||||||
|
'UF',
|
||||||
|
'IPC'
|
||||||
|
]
|
||||||
|
const row = $('<tr></tr>')
|
||||||
|
columns.forEach(title => {
|
||||||
|
row.append(
|
||||||
|
$('<th></th>').html(title)
|
||||||
|
)
|
||||||
|
})
|
||||||
|
thead.append(row)
|
||||||
|
return thead
|
||||||
|
},
|
||||||
|
tbody: proyecto_idx => {
|
||||||
|
const tbody = $('<tbody></tbody>')
|
||||||
|
this.data[proyecto_idx].ventas.forEach(venta => {
|
||||||
|
venta.draw({tbody, valor_terreno: this.data[proyecto_idx].terreno.valor})
|
||||||
|
})
|
||||||
|
return tbody
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
actions: function() {
|
||||||
|
return {
|
||||||
|
up: event => {
|
||||||
|
this.draw().proyectos()
|
||||||
|
},
|
||||||
|
refresh: event => {
|
||||||
|
const list = $(this.ids.proyectos)
|
||||||
|
if (list.is(':hidden')) {
|
||||||
|
const table = $(this.ids.table)
|
||||||
|
table.hide()
|
||||||
|
if (this.table !== null) {
|
||||||
|
this.table.clear().destroy()
|
||||||
|
this.table = null
|
||||||
|
}
|
||||||
|
this.get().ventas()
|
||||||
|
} else {
|
||||||
|
this.draw().proyectos()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
setup: function({ids}) {
|
||||||
|
this.ids = ids
|
||||||
|
$(this.ids.data).hide()
|
||||||
|
$(this.ids.proyectos).find('.item').click(event => {
|
||||||
|
this.selected = $(event.currentTarget).data('proyecto')
|
||||||
|
this.get().ventas()
|
||||||
|
})
|
||||||
|
|
||||||
|
$(this.ids.buttons.up).click(this.actions().up)
|
||||||
|
$(this.ids.buttons.refresh).click(this.actions().refresh)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$(document).ready(() => {
|
||||||
|
proyectos.setup({ids: {
|
||||||
|
proyectos: '#proyectos',
|
||||||
|
data: '#data',
|
||||||
|
buttons: {
|
||||||
|
up: '#up_button',
|
||||||
|
refresh: '#refresh_button'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
@endpush
|
11
app/resources/views/ventas/facturacion/show.blade.php
Normal file
11
app/resources/views/ventas/facturacion/show.blade.php
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
@extends('layout.base')
|
||||||
|
|
||||||
|
@section('page_content')
|
||||||
|
<div class="ui container">
|
||||||
|
<form id="venta_form">
|
||||||
|
<div class="field">
|
||||||
|
<label for=""></label>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
@endsection
|
@ -1,2 +1,3 @@
|
|||||||
<?php
|
<?php
|
||||||
$app->add($app->getContainer()->get(Incoviba\Middleware\NotFound::class));
|
$app->add($app->getContainer()->get(Incoviba\Middleware\NotFound::class));
|
||||||
|
$app->add($app->getContainer()->get(Incoviba\Middleware\Errors::class));
|
||||||
|
@ -12,7 +12,8 @@ return [
|
|||||||
},
|
},
|
||||||
Incoviba\Common\Define\Connection::class => function(ContainerInterface $container) {
|
Incoviba\Common\Define\Connection::class => function(ContainerInterface $container) {
|
||||||
return new Incoviba\Common\Implement\Connection(
|
return new Incoviba\Common\Implement\Connection(
|
||||||
$container->get(Incoviba\Common\Define\Database::class)
|
$container->get(Incoviba\Common\Define\Database::class),
|
||||||
|
$container->get(Incoviba\Common\Implement\Database\Query\Builder::class)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
123
app/src/Controller/API/Money.php
Normal file
123
app/src/Controller/API/Money.php
Normal file
@ -0,0 +1,123 @@
|
|||||||
|
<?php
|
||||||
|
namespace Incoviba\Controller\API;
|
||||||
|
|
||||||
|
use DateTimeInterface;
|
||||||
|
use DateTimeImmutable;
|
||||||
|
use DateInterval;
|
||||||
|
use Psr\Http\Message\ResponseInterface;
|
||||||
|
use Psr\Http\Message\ServerRequestInterface;
|
||||||
|
use Incoviba\Common\Implement\Exception\EmptyRedis;
|
||||||
|
use Incoviba\Service;
|
||||||
|
|
||||||
|
class Money
|
||||||
|
{
|
||||||
|
use withJson, withRedis;
|
||||||
|
|
||||||
|
private int $time = 60 * 60 * 24 * 30;
|
||||||
|
|
||||||
|
public function get(ServerRequestInterface $request, ResponseInterface $response, Service\Redis $redisService, Service\Money $moneyService): ResponseInterface
|
||||||
|
{
|
||||||
|
$data = $request->getParsedBody();
|
||||||
|
$output = [
|
||||||
|
'input' => $data
|
||||||
|
];
|
||||||
|
$output[$data['provider']] = 0;
|
||||||
|
$redisKey = $data['provider'];
|
||||||
|
$date = new DateTimeImmutable($data['fecha']);
|
||||||
|
if (isset($data['start'])) {
|
||||||
|
$start = new DateTimeImmutable($data['start']);
|
||||||
|
}
|
||||||
|
$value = $this->getValue($redisService, $redisKey, $moneyService, $date, $data['provider']);
|
||||||
|
if (isset($start)) {
|
||||||
|
$months = $date->diff($start)->m;
|
||||||
|
$current = clone $start;
|
||||||
|
$value = $this->getValue($redisService, $redisKey, $moneyService, $current, $data['provider']);
|
||||||
|
for ($i = 1; $i <= $months; $i ++) {
|
||||||
|
$current = $current->add(new DateInterval("P{$i}M"));
|
||||||
|
$value += $this->getValue($redisService, $redisKey, $moneyService, $current, $data['provider']);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$output[$data['provider']] = $value;
|
||||||
|
return $this->withJson($response, $output);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected array $data;
|
||||||
|
protected function getValue(Service\Redis $redisService, string $redisKey, Service\Money $moneyService, DateTimeInterface $date, string $provider): float
|
||||||
|
{
|
||||||
|
if (isset($this->data[$date->format('Y-m-d')])) {
|
||||||
|
return $this->data[$date->format('Y-m-d')];
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
$this->data = (array) $this->fetchRedis($redisService, $redisKey);
|
||||||
|
if (!isset($this->data[$date->format('Y-m-d')])) {
|
||||||
|
throw new EmptyRedis($redisKey);
|
||||||
|
}
|
||||||
|
} catch (EmptyRedis) {
|
||||||
|
$result = $moneyService->get($provider, $date);
|
||||||
|
$this->data[$date->format('Y-m-d')] = $result;
|
||||||
|
$this->saveRedis($redisService, $redisKey, $this->data, $this->time);
|
||||||
|
}
|
||||||
|
return $this->data[$date->format('Y-m-d')];
|
||||||
|
}
|
||||||
|
/*public function uf(ServerRequestInterface $request, ResponseInterface $response, Service\Redis $redisService, Service\Money $moneyService): ResponseInterface
|
||||||
|
{
|
||||||
|
$body = $request->getParsedBody();
|
||||||
|
$output = [
|
||||||
|
'input' => $body,
|
||||||
|
'uf' => 0
|
||||||
|
];
|
||||||
|
$redisKey = 'uf';
|
||||||
|
$date = new DateTimeImmutable($body['fecha']);
|
||||||
|
try {
|
||||||
|
$ufs = $this->fetchRedis($redisService, $redisKey);
|
||||||
|
if (!isset($ufs[$date->format('Y-m-d')])) {
|
||||||
|
throw new EmptyRedis($redisKey);
|
||||||
|
}
|
||||||
|
} catch (EmptyRedis) {
|
||||||
|
error_log(var_export($ufs,true));
|
||||||
|
if (!isset($ufs)) {
|
||||||
|
$ufs = [];
|
||||||
|
}
|
||||||
|
$uf = $moneyService->getUF($date);
|
||||||
|
$ufs[$date->format('Y-m-d')] = $uf;
|
||||||
|
$this->saveRedis($redisService, $redisKey, $ufs, 60 * 60 * 24 * 30);
|
||||||
|
}
|
||||||
|
$output['uf'] = $ufs[$date->format('Y-m-d')];
|
||||||
|
return $this->withJson($response, $output);
|
||||||
|
}*/
|
||||||
|
public function ipc(ServerRequestInterface $request, ResponseInterface $response, Service\Redis $redisService, Service\Money $moneyService): ResponseInterface
|
||||||
|
{
|
||||||
|
$data = $request->getParsedBody();
|
||||||
|
$output = [
|
||||||
|
'input' => $data,
|
||||||
|
'date_string' => '',
|
||||||
|
'ipc' => 0
|
||||||
|
];
|
||||||
|
$redisKey = 'ipc';
|
||||||
|
$start = new DateTimeImmutable($data['start']);
|
||||||
|
$end = new DateTimeImmutable($data['end']);
|
||||||
|
$now = new DateTimeImmutable();
|
||||||
|
if ($end > $now) {
|
||||||
|
return $this->withJson($response, $output);
|
||||||
|
}
|
||||||
|
$dateKey = "{$start->format('Y-m')}-{$end->format('Y-m')}";
|
||||||
|
$months = $start->diff($end)->m;
|
||||||
|
$current = new DateTimeImmutable((($start <= $end) ? $start : $end)->format('Y-m-15'));
|
||||||
|
$value = 0;
|
||||||
|
$ipcs = [];
|
||||||
|
try {
|
||||||
|
$ipcs = (array) $this->fetchRedis($redisService, $redisKey);
|
||||||
|
} catch (EmptyRedis) {}
|
||||||
|
for ($i = 1; $i < $months; $i ++) {
|
||||||
|
$current = $current->add(new DateInterval("P1M"));
|
||||||
|
if (!isset($ipcs[$current->format('Y-m')])) {
|
||||||
|
$ipcs[$current->format('Y-m')] = $moneyService->getIPC($current);
|
||||||
|
$this->saveRedis($redisService, $redisKey, $ipcs, $this->time);
|
||||||
|
}
|
||||||
|
$value += $ipcs[$current->format('Y-m')];
|
||||||
|
}
|
||||||
|
$output['date_string'] = $dateKey;
|
||||||
|
$output['ipc'] = $value;
|
||||||
|
return $this->withJson($response, $output);
|
||||||
|
}
|
||||||
|
}
|
@ -2,9 +2,9 @@
|
|||||||
namespace Incoviba\Controller\API;
|
namespace Incoviba\Controller\API;
|
||||||
|
|
||||||
use DateTimeImmutable;
|
use DateTimeImmutable;
|
||||||
use Incoviba\Common\Implement\Exception\EmptyRedis;
|
|
||||||
use Psr\Http\Message\ResponseInterface;
|
use Psr\Http\Message\ResponseInterface;
|
||||||
use Psr\Http\Message\ServerRequestInterface;
|
use Psr\Http\Message\ServerRequestInterface;
|
||||||
|
use Incoviba\Common\Implement\Exception\EmptyRedis;
|
||||||
use Incoviba\Common\Implement\Exception\EmptyResult;
|
use Incoviba\Common\Implement\Exception\EmptyResult;
|
||||||
use Incoviba\Model;
|
use Incoviba\Model;
|
||||||
use Incoviba\Repository;
|
use Incoviba\Repository;
|
||||||
@ -153,4 +153,21 @@ class Ventas
|
|||||||
}
|
}
|
||||||
return $this->withJson($response, $output);
|
return $this->withJson($response, $output);
|
||||||
}
|
}
|
||||||
|
public function unidades(ServerRequestInterface $request, ResponseInterface $response, Service\Venta\Unidad $unidadService, int $venta_id): ResponseInterface
|
||||||
|
{
|
||||||
|
$output = [
|
||||||
|
'venta_id' => $venta_id,
|
||||||
|
'unidades' => []
|
||||||
|
];
|
||||||
|
try {
|
||||||
|
$unidades = $unidadService->getByVenta($venta_id);
|
||||||
|
$output['unidades'] = json_decode(json_encode($unidades));
|
||||||
|
array_walk($output['unidades'], function($unidad, $index, $unidades) {
|
||||||
|
$unidad->prorrateo = $unidades[$index]->prorrateo;
|
||||||
|
$unidad->precios = $unidades[$index]->precios;
|
||||||
|
$unidad->current_precio = $unidades[$index]->currentPrecio;
|
||||||
|
}, $unidades);
|
||||||
|
} catch (EmptyResult) {}
|
||||||
|
return $this->withJson($response, $output);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
36
app/src/Controller/API/Ventas/Facturacion.php
Normal file
36
app/src/Controller/API/Ventas/Facturacion.php
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
<?php
|
||||||
|
namespace Incoviba\Controller\API\Ventas;
|
||||||
|
|
||||||
|
use DateTimeImmutable;
|
||||||
|
use Psr\Http\Message\ResponseInterface;
|
||||||
|
use Psr\Http\Message\ServerRequestInterface;
|
||||||
|
use Incoviba\Service;
|
||||||
|
use Incoviba\Controller\API\withJson;
|
||||||
|
use Incoviba\Controller\API\withRedis;
|
||||||
|
use Incoviba\Controller\API\emptyBody;
|
||||||
|
use Incoviba\Common\Implement\Exception\EmptyResult;
|
||||||
|
use Incoviba\Common\Implement\Exception\EmptyRedis;
|
||||||
|
|
||||||
|
class Facturacion
|
||||||
|
{
|
||||||
|
use withJson, withRedis, emptyBody;
|
||||||
|
|
||||||
|
public function proyecto(ServerRequestInterface $request, ResponseInterface $response, Service\Redis $redisService, Service\Venta $ventaService, int $proyecto_id): ResponseInterface
|
||||||
|
{
|
||||||
|
$output = [
|
||||||
|
'proyecto_id' => $proyecto_id,
|
||||||
|
'ventas' => []
|
||||||
|
];
|
||||||
|
$today = new DateTimeImmutable();
|
||||||
|
$redisKey = "ventas_facturacion-proyecto-{$proyecto_id}-{$today->format('Y-m-d')}";
|
||||||
|
try {
|
||||||
|
$output['ventas'] = $this->fetchRedis($redisService, $redisKey);
|
||||||
|
} catch (EmptyRedis) {
|
||||||
|
try {
|
||||||
|
$output['ventas'] = $ventaService->getActivaByProyecto($proyecto_id);
|
||||||
|
$this->saveRedis($redisService, $redisKey, $output['ventas']);
|
||||||
|
} catch (EmptyResult) {}
|
||||||
|
}
|
||||||
|
return $this->withJson($response, $output);
|
||||||
|
}
|
||||||
|
}
|
@ -14,11 +14,15 @@ trait withRedis
|
|||||||
}
|
}
|
||||||
return json_decode($jsonString);
|
return json_decode($jsonString);
|
||||||
}
|
}
|
||||||
public function saveRedis(Service\Redis $redisService, string $redisKey, mixed $value): void
|
public function saveRedis(Service\Redis $redisService, string $redisKey, mixed $value, ?int $expiration = null): void
|
||||||
{
|
{
|
||||||
if (is_array($value) or is_object($value)) {
|
if (is_array($value) or is_object($value)) {
|
||||||
$value = json_encode($value);
|
$value = json_encode($value);
|
||||||
}
|
}
|
||||||
|
if ($expiration !== null) {
|
||||||
|
$redisService->set($redisKey, $value, $expiration);
|
||||||
|
return;
|
||||||
|
}
|
||||||
$redisService->set($redisKey, $value);
|
$redisService->set($redisKey, $value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
21
app/src/Controller/Ventas/Facturacion.php
Normal file
21
app/src/Controller/Ventas/Facturacion.php
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
<?php
|
||||||
|
namespace Incoviba\Controller\Ventas;
|
||||||
|
|
||||||
|
use Psr\Http\Message\ResponseInterface;
|
||||||
|
use Psr\Http\Message\ServerRequestInterface;
|
||||||
|
use Incoviba\Common\Alias\View;
|
||||||
|
use Incoviba\Service;
|
||||||
|
|
||||||
|
class Facturacion
|
||||||
|
{
|
||||||
|
public function __invoke(ServerRequestInterface $request, ResponseInterface $response, View $view, Service\Proyecto $proyectoService): ResponseInterface
|
||||||
|
{
|
||||||
|
$proyectos = $proyectoService->getEscriturando();
|
||||||
|
return $view->render($response, 'ventas.facturacion', compact('proyectos'));
|
||||||
|
}
|
||||||
|
public function show(ServerRequestInterface $request, ResponseInterface $response, View $view, Service\Venta $ventaService, int $venta_id): ResponseInterface
|
||||||
|
{
|
||||||
|
$venta = $ventaService->getById($venta_id);
|
||||||
|
return $view->render($response, 'ventas.facturacion.show', compact('venta'));
|
||||||
|
}
|
||||||
|
}
|
31
app/src/Middleware/Errors.php
Normal file
31
app/src/Middleware/Errors.php
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
<?php
|
||||||
|
namespace Incoviba\Middleware;
|
||||||
|
|
||||||
|
use Error;
|
||||||
|
use Exception;
|
||||||
|
use Psr\Http\Message\ResponseFactoryInterface;
|
||||||
|
use Psr\Http\Message\ResponseInterface;
|
||||||
|
use Psr\Http\Message\ServerRequestInterface;
|
||||||
|
use Psr\Http\Server\RequestHandlerInterface;
|
||||||
|
use Psr\Log\LoggerInterface;
|
||||||
|
use Incoviba\Common\Alias\View;
|
||||||
|
|
||||||
|
class Errors
|
||||||
|
{
|
||||||
|
public function __construct(protected LoggerInterface $logger, protected ResponseFactoryInterface $responseFactory, protected View $view) {}
|
||||||
|
public function __invoke(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
return $handler->handle($request);
|
||||||
|
} catch (Exception $exception) {
|
||||||
|
$this->logger->notice($exception);
|
||||||
|
} catch (Error $error) {
|
||||||
|
$this->logger->error($error);
|
||||||
|
}
|
||||||
|
$response = $this->responseFactory->createResponse(404);
|
||||||
|
if (str_contains($request->getUri()->getPath(), '/api')) {
|
||||||
|
return $response;
|
||||||
|
}
|
||||||
|
return $this->view->render($response, 'construccion');
|
||||||
|
}
|
||||||
|
}
|
@ -1,7 +1,9 @@
|
|||||||
<?php
|
<?php
|
||||||
namespace Incoviba\Model\Proyecto;
|
namespace Incoviba\Model\Proyecto;
|
||||||
|
|
||||||
class Superficie
|
use JsonSerializable;
|
||||||
|
|
||||||
|
class Superficie implements JsonSerializable
|
||||||
{
|
{
|
||||||
public float $sobre_nivel;
|
public float $sobre_nivel;
|
||||||
public float $bajo_nivel;
|
public float $bajo_nivel;
|
||||||
@ -10,4 +12,13 @@ class Superficie
|
|||||||
{
|
{
|
||||||
return $this->bajo_nivel + $this->sobre_nivel;
|
return $this->bajo_nivel + $this->sobre_nivel;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function jsonSerialize(): mixed
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'sobre_nivel' => $this->sobre_nivel,
|
||||||
|
'bajo_nivel' => $this->bajo_nivel,
|
||||||
|
'total' => $this->total()
|
||||||
|
];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,21 @@
|
|||||||
<?php
|
<?php
|
||||||
namespace Incoviba\Model\Proyecto;
|
namespace Incoviba\Model\Proyecto;
|
||||||
|
|
||||||
class Terreno
|
use DateTimeInterface;
|
||||||
|
use JsonSerializable;
|
||||||
|
|
||||||
|
class Terreno implements JsonSerializable
|
||||||
{
|
{
|
||||||
public float $superficie;
|
public float $superficie;
|
||||||
public float $valor;
|
public float $valor;
|
||||||
|
public ?DateTimeInterface $date;
|
||||||
|
|
||||||
|
public function jsonSerialize(): mixed
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'superficie' => $this->superficie,
|
||||||
|
'valor' => $this->valor,
|
||||||
|
'date' => $this->date?->format('Y-m-d')
|
||||||
|
];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -12,6 +12,7 @@ class Unidad extends Ideal\Model
|
|||||||
public string $descripcion;
|
public string $descripcion;
|
||||||
public ?string $orientacion = '';
|
public ?string $orientacion = '';
|
||||||
public Model\Proyecto\ProyectoTipoUnidad $proyectoTipoUnidad;
|
public Model\Proyecto\ProyectoTipoUnidad $proyectoTipoUnidad;
|
||||||
|
public ?float $prorrateo;
|
||||||
|
|
||||||
public array $precios = [];
|
public array $precios = [];
|
||||||
public ?Precio $currentPrecio = null;
|
public ?Precio $currentPrecio = null;
|
||||||
@ -50,7 +51,8 @@ class Unidad extends Ideal\Model
|
|||||||
'piso' => $this->piso,
|
'piso' => $this->piso,
|
||||||
'descripcion' => $this->descripcion,
|
'descripcion' => $this->descripcion,
|
||||||
'orientacion' => $this->orientacion,
|
'orientacion' => $this->orientacion,
|
||||||
'proyecto_tipo_unidad' => $this->proyectoTipoUnidad
|
'proyecto_tipo_unidad' => $this->proyectoTipoUnidad,
|
||||||
|
'prorrateo' => $this->prorrateo
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
<?php
|
<?php
|
||||||
namespace Incoviba\Repository;
|
namespace Incoviba\Repository;
|
||||||
|
|
||||||
|
use DateTimeImmutable;
|
||||||
use Incoviba\Common\Define;
|
use Incoviba\Common\Define;
|
||||||
use Incoviba\Common\Ideal;
|
use Incoviba\Common\Ideal;
|
||||||
use Incoviba\Common\Implement;
|
use Incoviba\Common\Implement;
|
||||||
@ -36,6 +37,10 @@ class Proyecto extends Ideal\Repository
|
|||||||
$terreno = new Model\Proyecto\Terreno();
|
$terreno = new Model\Proyecto\Terreno();
|
||||||
$terreno->superficie = $data['superficie_terreno'];
|
$terreno->superficie = $data['superficie_terreno'];
|
||||||
$terreno->valor = $data['valor_terreno'];
|
$terreno->valor = $data['valor_terreno'];
|
||||||
|
$terreno->date = null;
|
||||||
|
if (isset($data['fecha_terreno']) and $data['fecha_terreno'] !== '') {
|
||||||
|
$terreno->date = new DateTimeImmutable($data['fecha_terreno']);
|
||||||
|
}
|
||||||
return $terreno;
|
return $terreno;
|
||||||
}))
|
}))
|
||||||
->register('superficie_sobre_nivel', (new Implement\Repository\Mapper())
|
->register('superficie_sobre_nivel', (new Implement\Repository\Mapper())
|
||||||
@ -67,36 +72,55 @@ class Proyecto extends Ideal\Repository
|
|||||||
}
|
}
|
||||||
public function fetchByName(string $name): Define\Model
|
public function fetchByName(string $name): Define\Model
|
||||||
{
|
{
|
||||||
$query = "SELECT * FROM `{$this->getTable()}` WHERE `name` = ?";
|
$query = $this->connection->getQueryBuilder()
|
||||||
|
->select($this->columns())
|
||||||
|
->from("{$this->getTable()} a")
|
||||||
|
->joined($this->joinTerreno())
|
||||||
|
->where("name = ?");
|
||||||
return $this->fetchOne($query, [$name]);
|
return $this->fetchOne($query, [$name]);
|
||||||
}
|
}
|
||||||
public function fetchAllActive(): array
|
public function fetchAllActive(): array
|
||||||
{
|
{
|
||||||
$etapaProyecto = $this->etapaRepository->fetchByDescripcion('Proyecto');
|
$etapaProyecto = $this->etapaRepository->fetchByDescripcion('Proyecto');
|
||||||
$etapaTerminado = $this->etapaRepository->fetchByDescripcion('Terminado');
|
$etapaTerminado = $this->etapaRepository->fetchByDescripcion('Terminado');
|
||||||
$query = "SELECT a.*
|
$query = $this->connection->getQueryBuilder()
|
||||||
FROM `{$this->getTable()}` a
|
->select($this->columns())
|
||||||
{$this->joinEstado()}
|
->from("{$this->getTable()} a")
|
||||||
WHERE et.`orden` BETWEEN {$etapaProyecto->orden} AND ({$etapaTerminado->orden} - 1)
|
->joined($this->joinTerreno())
|
||||||
ORDER BY a.`descripcion`";
|
->joined($this->joinEstado())
|
||||||
|
->where("et.orden BETWEEN {$etapaProyecto->orden} AND ({$etapaTerminado->orden} - 1)")
|
||||||
|
->order('a.descripcion');
|
||||||
return $this->fetchMany($query);
|
return $this->fetchMany($query);
|
||||||
}
|
}
|
||||||
public function fetchAllEscriturando(): array
|
public function fetchAllEscriturando(): array
|
||||||
{
|
{
|
||||||
$etapaRecepcion = $this->etapaRepository->fetchByDescripcion('Recepción');
|
$etapaRecepcion = $this->etapaRepository->fetchByDescripcion('Recepción');
|
||||||
$etapaTerminado = $this->etapaRepository->fetchByDescripcion('Terminado');
|
$etapaTerminado = $this->etapaRepository->fetchByDescripcion('Terminado');
|
||||||
$query = "SELECT a.*
|
$query = $this->connection->getQueryBuilder()
|
||||||
FROM `{$this->getTable()}` a
|
->select($this->columns())
|
||||||
{$this->joinEstado()}
|
->from("{$this->getTable()} a")
|
||||||
WHERE et.`orden` BETWEEN {$etapaRecepcion->orden} AND ({$etapaTerminado->orden} - 1)
|
->joined($this->joinTerreno())
|
||||||
ORDER BY a.`descripcion`";
|
->joined($this->joinEstado())
|
||||||
|
->where("et.orden BETWEEN {$etapaRecepcion->orden} AND ({$etapaTerminado->orden} - 1)")
|
||||||
|
->order('a.descripcion');
|
||||||
return $this->fetchMany($query);
|
return $this->fetchMany($query);
|
||||||
}
|
}
|
||||||
public function fetchSuperficieVendido(int $proyecto_id): float
|
/*public function fetchSuperficieVendido(int $proyecto_id): float
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}*/
|
||||||
|
|
||||||
|
protected function columns(): string
|
||||||
|
{
|
||||||
|
return "a.id, a.inmobiliaria, a.descripcion, a.direccion, a.superficie_terreno,
|
||||||
|
COALESCE(pt.valor, a.valor_terreno) AS valor_terreno, COALESCE(pt.fecha, '') AS fecha_terreno, a.corredor,
|
||||||
|
a.superficie_sobre_nivel, a.superficie_bajo_nivel, a.pisos, a.subterraneos";
|
||||||
|
}
|
||||||
|
protected function joinTerreno(): string
|
||||||
|
{
|
||||||
|
return "LEFT OUTER JOIN (SELECT pt1.* FROM proyecto_terreno pt1 JOIN (
|
||||||
|
SELECT MAX(id) AS id, proyecto_id FROM proyecto_terreno) pt0 ON pt0.id = pt1.id) pt ON pt.proyecto_id = a.id";
|
||||||
|
}
|
||||||
protected function joinEstado(): string
|
protected function joinEstado(): string
|
||||||
{
|
{
|
||||||
return "JOIN (
|
return "JOIN (
|
||||||
|
@ -17,7 +17,7 @@ class Unidad extends Ideal\Repository
|
|||||||
|
|
||||||
public function create(?array $data = null): Model\Venta\Unidad
|
public function create(?array $data = null): Model\Venta\Unidad
|
||||||
{
|
{
|
||||||
$map = (new Implement\Repository\MapperParser(['subtipo', 'piso', 'descripcion', 'orientacion']))
|
$map = (new Implement\Repository\MapperParser(['subtipo', 'piso', 'descripcion', 'orientacion', 'prorrateo']))
|
||||||
->register('pt', (new Implement\Repository\Mapper())
|
->register('pt', (new Implement\Repository\Mapper())
|
||||||
->setProperty('proyectoTipoUnidad')
|
->setProperty('proyectoTipoUnidad')
|
||||||
->setFunction(function($data) {
|
->setFunction(function($data) {
|
||||||
@ -38,62 +38,88 @@ class Unidad extends Ideal\Repository
|
|||||||
return $this->update($model, ['subtipo', 'piso', 'descripcion', 'orientacion', 'pt'], $new_data);
|
return $this->update($model, ['subtipo', 'piso', 'descripcion', 'orientacion', 'pt'], $new_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function fetchByVenta(int $venta_id): array
|
||||||
|
{
|
||||||
|
$query = $this->connection->getQueryBuilder()
|
||||||
|
->select('a.*, up.prorrateo')
|
||||||
|
->from("{$this->getTable()} a")
|
||||||
|
->joined($this->joinProrrateo())
|
||||||
|
->joined('JOIN propiedad_unidad pu ON pu.unidad = a.id
|
||||||
|
JOIN venta ON venta.propiedad = pu.propiedad')
|
||||||
|
->where('venta.id = ?');
|
||||||
|
return $this->fetchMany($query, [$venta_id]);
|
||||||
|
}
|
||||||
public function fetchByPropiedad(int $propiedad_id): array
|
public function fetchByPropiedad(int $propiedad_id): array
|
||||||
{
|
{
|
||||||
$query = "SELECT a.*
|
$query = $this->connection->getQueryBuilder()
|
||||||
FROM `{$this->getTable()}` a
|
->select('a.*, up.prorrateo')
|
||||||
JOIN `propiedad_unidad` pu ON pu.`unidad` = a.`id`
|
->from("{$this->getTable()} a")
|
||||||
WHERE pu.`propiedad` = ?
|
->joined($this->joinProrrateo())
|
||||||
GROUP BY a.`id`";
|
->joined('JOIN `propiedad_unidad` pu ON pu.`unidad` = a.`id`')
|
||||||
|
->where('pu.propiedad = ?')
|
||||||
|
->group('a.id');
|
||||||
return $this->fetchMany($query, [$propiedad_id]);
|
return $this->fetchMany($query, [$propiedad_id]);
|
||||||
}
|
}
|
||||||
public function fetchByCierre(int $cierre_id): array
|
public function fetchByCierre(int $cierre_id): array
|
||||||
{
|
{
|
||||||
$query = "SELECT a.*
|
$query = $this->connection->getQueryBuilder()
|
||||||
FROM `{$this->getTable()}` a
|
->select('a.*, up.prorrateo')
|
||||||
JOIN `unidad_cierre` uc ON uc.`unidad` = a.`id`
|
->from("{$this->getTable()} a")
|
||||||
|
->joined($this->joinProrrateo())
|
||||||
|
->joined("JOIN `unidad_cierre` uc ON uc.`unidad` = a.`id`
|
||||||
JOIN `proyecto_tipo_unidad` ptu ON ptu.`id` = a.`pt`
|
JOIN `proyecto_tipo_unidad` ptu ON ptu.`id` = a.`pt`
|
||||||
JOIN `tipo_unidad` tu ON tu.`id` = ptu.`tipo`
|
JOIN `tipo_unidad` tu ON tu.`id` = ptu.`tipo`")
|
||||||
WHERE uc.`cierre` = ?
|
->where('uc.cierre = ?')
|
||||||
GROUP BY a.`id`
|
->group('a.id')
|
||||||
ORDER BY tu.`orden`, LPAD(a.`descripcion`, 4, '0')";
|
->order("tu.orden, LPAD(a.descripcion, 4, '0')");
|
||||||
return $this->fetchMany($query, [$cierre_id]);
|
return $this->fetchMany($query, [$cierre_id]);
|
||||||
}
|
}
|
||||||
public function fetchByProyecto(int $proyecto_id): array
|
public function fetchByProyecto(int $proyecto_id): array
|
||||||
{
|
{
|
||||||
$query = "SELECT a.*
|
$query = $this->connection->getQueryBuilder()
|
||||||
FROM `{$this->getTable()}` a
|
->select('a.*, up.prorrateo')
|
||||||
JOIN `proyecto_tipo_unidad` ptu ON ptu.`id` = a.`pt`
|
->from("{$this->getTable()} a")
|
||||||
JOIN `tipo_unidad` tu ON tu.`id` = ptu.`tipo`
|
->joined($this->joinProrrateo())
|
||||||
WHERE ptu.`proyecto` = ?
|
->joined("JOIN `proyecto_tipo_unidad` ptu ON ptu.`id` = a.`pt`
|
||||||
ORDER BY tu.`orden`";
|
JOIN `tipo_unidad` tu ON tu.`id` = ptu.`tipo`")
|
||||||
|
->where('ptu.proyecto = ?')
|
||||||
|
->order('tu.orden');
|
||||||
return $this->fetchMany($query, [$proyecto_id]);
|
return $this->fetchMany($query, [$proyecto_id]);
|
||||||
}
|
}
|
||||||
public function fetchDisponiblesByProyecto(int $proyecto_id): array
|
public function fetchDisponiblesByProyecto(int $proyecto_id): array
|
||||||
{
|
{
|
||||||
$query = "SELECT DISTINCT a.*
|
$query = $this->connection->getQueryBuilder()
|
||||||
FROM `{$this->getTable()}` a
|
->select('DISTINCT a.*, up.prorrateo')
|
||||||
JOIN `proyecto_tipo_unidad` ptu ON ptu.`id` = a.`pt`
|
->from("{$this->getTable()} a")
|
||||||
|
->joined($this->joinProrrateo())
|
||||||
|
->joined("JOIN `proyecto_tipo_unidad` ptu ON ptu.`id` = a.`pt`
|
||||||
JOIN `tipo_unidad` tu ON tu.`id` = ptu.`tipo`
|
JOIN `tipo_unidad` tu ON tu.`id` = ptu.`tipo`
|
||||||
LEFT OUTER JOIN `propiedad_unidad` pu ON pu.`unidad` = a.`id`
|
LEFT OUTER JOIN `propiedad_unidad` pu ON pu.`unidad` = a.`id`
|
||||||
LEFT OUTER JOIN `venta` ON `venta`.`propiedad` = `pu`.`propiedad`
|
LEFT OUTER JOIN `venta` ON `venta`.`propiedad` = `pu`.`propiedad`
|
||||||
LEFT OUTER JOIN (SELECT ev1.* FROM `estado_venta` ev1 JOIN (SELECT MAX(`id`) as 'id', `venta` FROM `estado_venta`) ev0 ON ev0.`id` = ev1.`id`) ev ON ev.`venta` = `venta`.`id`
|
LEFT OUTER JOIN (SELECT ev1.* FROM `estado_venta` ev1 JOIN (SELECT MAX(`id`) as 'id', `venta` FROM `estado_venta`) ev0 ON ev0.`id` = ev1.`id`) ev ON ev.`venta` = `venta`.`id`
|
||||||
LEFT OUTER JOIN `tipo_estado_venta` tev ON tev.`id` = ev.`estado`
|
LEFT OUTER JOIN `tipo_estado_venta` tev ON tev.`id` = ev.`estado`")
|
||||||
WHERE ptu.`proyecto` = ? AND (pu.`id` IS NULL OR `venta`.`id` IS NULL OR tev.`activa` = 0)
|
->where("ptu.`proyecto` = ? AND (pu.`id` IS NULL OR `venta`.`id` IS NULL OR tev.`activa` = 0)")
|
||||||
ORDER BY tu.`orden`";
|
->order('tu.orden');
|
||||||
return $this->fetchMany($query, [$proyecto_id]);
|
return $this->fetchMany($query, [$proyecto_id]);
|
||||||
}
|
}
|
||||||
public function fetchDisponiblesByDescripcionAndTipo(string $descripcion, string $tipo): array
|
public function fetchDisponiblesByDescripcionAndTipo(string $descripcion, string $tipo): array
|
||||||
{
|
{
|
||||||
$query = "SELECT DISTINCT a.*
|
$query = $this->connection->getQueryBuilder()
|
||||||
FROM `{$this->getTable()}` a
|
->select('DISTINCT a.*, up.prorrateo')
|
||||||
JOIN `proyecto_tipo_unidad` ptu ON ptu.`id` = a.`pt`
|
->from("{$this->getTable()} a")
|
||||||
|
->joined($this->joinProrrateo())
|
||||||
|
->joined("JOIN `proyecto_tipo_unidad` ptu ON ptu.`id` = a.`pt`
|
||||||
JOIN `tipo_unidad` tu ON tu.`id` = ptu.`tipo`
|
JOIN `tipo_unidad` tu ON tu.`id` = ptu.`tipo`
|
||||||
LEFT OUTER JOIN `propiedad_unidad` pu ON pu.`unidad` = a.`id`
|
LEFT OUTER JOIN `propiedad_unidad` pu ON pu.`unidad` = a.`id`
|
||||||
LEFT OUTER JOIN `venta` ON `venta`.`propiedad` = pu.`propiedad`
|
LEFT OUTER JOIN `venta` ON `venta`.`propiedad` = pu.`propiedad`
|
||||||
LEFT OUTER JOIN (SELECT ev1.* FROM `estado_venta` ev1 JOIN (SELECT MAX(`id`) as 'id', `venta` FROM `estado_venta`) ev0 ON ev0.`id` = ev1.`id`) ev ON ev.`venta` = `venta`.`id`
|
LEFT OUTER JOIN (SELECT ev1.* FROM `estado_venta` ev1 JOIN (SELECT MAX(`id`) as 'id', `venta` FROM `estado_venta`) ev0 ON ev0.`id` = ev1.`id`) ev ON ev.`venta` = `venta`.`id`
|
||||||
LEFT OUTER JOIN `tipo_estado_venta` tev ON tev.`id` = ev.`estado`
|
LEFT OUTER JOIN `tipo_estado_venta` tev ON tev.`id` = ev.`estado`")
|
||||||
WHERE a.`descripcion` LIKE ? AND tu.`descripcion` = ? AND (pu.`id` IS NULL OR `venta`.`id` IS NULL OR tev.`activa` = 0)";
|
->where("a.`descripcion` LIKE ? AND tu.`descripcion` = ? AND (pu.`id` IS NULL OR `venta`.`id` IS NULL OR tev.`activa` = 0)");
|
||||||
return $this->fetchMany($query, [$descripcion, $tipo]);
|
return $this->fetchMany($query, [$descripcion, $tipo]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected function joinProrrateo(): string
|
||||||
|
{
|
||||||
|
return "LEFT OUTER JOIN unidad_prorrateo up ON up.unidad_id = a.id";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,8 @@
|
|||||||
namespace Incoviba\Service;
|
namespace Incoviba\Service;
|
||||||
|
|
||||||
use DateTimeInterface;
|
use DateTimeInterface;
|
||||||
|
use DateTimeImmutable;
|
||||||
|
use DateInterval;
|
||||||
use Incoviba\Common\Define\Money\Provider;
|
use Incoviba\Common\Define\Money\Provider;
|
||||||
use Incoviba\Common\Implement\Exception\EmptyResponse;
|
use Incoviba\Common\Implement\Exception\EmptyResponse;
|
||||||
use Incoviba\Service\Money\MiIndicador;
|
use Incoviba\Service\Money\MiIndicador;
|
||||||
@ -22,6 +24,15 @@ class Money
|
|||||||
return $this->providers[$name];
|
return $this->providers[$name];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function get(string $provider, DateTimeInterface $dateTime): float
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$upper = strtoupper($provider);
|
||||||
|
return $this->getProvider($provider)->get(MiIndicador::getSymbol($provider), $dateTime);
|
||||||
|
} catch (EmptyResponse) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
public function getUF(DateTimeInterface $dateTime): float
|
public function getUF(DateTimeInterface $dateTime): float
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
|
@ -36,4 +36,11 @@ class MiIndicador implements Provider
|
|||||||
}
|
}
|
||||||
return $json->serie[0]->valor;
|
return $json->serie[0]->valor;
|
||||||
}
|
}
|
||||||
|
public static function getSymbol(string $identifier): string
|
||||||
|
{
|
||||||
|
$upper = strtoupper($identifier);
|
||||||
|
$output = '';
|
||||||
|
eval("\$output = self::{$upper};");
|
||||||
|
return $output;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -15,6 +15,10 @@ class Proyecto
|
|||||||
{
|
{
|
||||||
return $this->proyectoRepository->fetchAllActive();
|
return $this->proyectoRepository->fetchAllActive();
|
||||||
}
|
}
|
||||||
|
public function getEscriturando(): array
|
||||||
|
{
|
||||||
|
return $this->proyectoRepository->fetchAllEscriturando();
|
||||||
|
}
|
||||||
public function getById(int $venta_id): Model\Proyecto
|
public function getById(int $venta_id): Model\Proyecto
|
||||||
{
|
{
|
||||||
return $this->process($this->proyectoRepository->fetchById($venta_id));
|
return $this->process($this->proyectoRepository->fetchById($venta_id));
|
||||||
|
@ -15,35 +15,32 @@ class Unidad
|
|||||||
|
|
||||||
public function getById(int $unidad_id): Model\Venta\Unidad
|
public function getById(int $unidad_id): Model\Venta\Unidad
|
||||||
{
|
{
|
||||||
$unidad = $this->unidadRepository->fetchById($unidad_id);
|
return $this->process($this->unidadRepository->fetchById($unidad_id));
|
||||||
$this->fillPrecios($unidad);
|
}
|
||||||
return $unidad;
|
public function getByVenta(int $venta_id): array
|
||||||
|
{
|
||||||
|
return array_map([$this, 'process'], $this->unidadRepository->fetchByVenta($venta_id));
|
||||||
}
|
}
|
||||||
public function getByPropiedad(int $propiedad_id): array
|
public function getByPropiedad(int $propiedad_id): array
|
||||||
{
|
{
|
||||||
$unidades = $this->unidadRepository->fetchByPropiedad($propiedad_id);
|
return array_map([$this, 'process'], $this->unidadRepository->fetchByPropiedad($propiedad_id));
|
||||||
array_walk($unidades, [$this, 'fillPrecios']);
|
|
||||||
return $unidades;
|
|
||||||
}
|
}
|
||||||
public function getByCierre(int $cierre_id): array
|
public function getByCierre(int $cierre_id): array
|
||||||
{
|
{
|
||||||
$unidades = $this->unidadRepository->fetchByCierre($cierre_id);
|
return array_map([$this, 'process'], $this->unidadRepository->fetchByCierre($cierre_id));
|
||||||
array_walk($unidades, [$this, 'fillPrecios']);
|
|
||||||
return $unidades;
|
|
||||||
}
|
}
|
||||||
public function getDisponiblesByProyecto(int $proyecto_id): array
|
public function getDisponiblesByProyecto(int $proyecto_id): array
|
||||||
{
|
{
|
||||||
$unidades = $this->unidadRepository->fetchDisponiblesByProyecto($proyecto_id);
|
return $this->unidadRepository->fetchDisponiblesByProyecto($proyecto_id);
|
||||||
//array_walk($unidades, [$this, 'fillPrecios']);
|
|
||||||
return $unidades;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function fillPrecios(&$unidad): void
|
protected function process($unidad): Model\Venta\Unidad
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
$unidad->precios = $this->precioService->getByUnidad($unidad->id);
|
$unidad->precios = $this->precioService->getByUnidad($unidad->id);
|
||||||
$unidad->currentPrecio = $this->precioService->getVigenteByUnidad($unidad->id);
|
$unidad->currentPrecio = $this->precioService->getVigenteByUnidad($unidad->id);
|
||||||
} catch (EmptyResult) {
|
} catch (EmptyResult) {
|
||||||
}
|
}
|
||||||
|
return $unidad;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user