Compare commits
1 commit
master
...
agregar-pr
Author | SHA1 | Date | |
---|---|---|---|
![]() |
95ba0733ab |
119 changed files with 1805 additions and 32168 deletions
|
@ -1,9 +0,0 @@
|
||||||
[Dolphin]
|
|
||||||
HeaderColumnWidths=372,72,103
|
|
||||||
SortRole=modificationtime
|
|
||||||
Timestamp=2022,6,1,16,36,48
|
|
||||||
Version=4
|
|
||||||
ViewMode=1
|
|
||||||
|
|
||||||
[Settings]
|
|
||||||
HiddenFilesShown=true
|
|
Binary file not shown.
|
@ -6,11 +6,9 @@ APP_URL=http://localhost
|
||||||
|
|
||||||
LOG_CHANNEL=stack
|
LOG_CHANNEL=stack
|
||||||
|
|
||||||
USERID=
|
|
||||||
|
|
||||||
DB_CONNECTION=mysql
|
DB_CONNECTION=mysql
|
||||||
DB_HOST=db
|
DB_HOST=db
|
||||||
DB_PORT_EXPOSED=3306
|
DB_PORT=3306
|
||||||
DB_DATABASE=pedi2
|
DB_DATABASE=pedi2
|
||||||
DB_USERNAME=pedi2
|
DB_USERNAME=pedi2
|
||||||
DB_PASSWORD=pedi2
|
DB_PASSWORD=pedi2
|
||||||
|
@ -50,4 +48,3 @@ MIX_PUSHER_APP_CLUSTER="${PUSHER_APP_CLUSTER}"
|
||||||
WEB_CLIENT_EMAIL=informaticamps@buzon.uy
|
WEB_CLIENT_EMAIL=informaticamps@buzon.uy
|
||||||
WEB_CLIENT_NAME=web
|
WEB_CLIENT_NAME=web
|
||||||
WEB_CLIENT_PASS=pass
|
WEB_CLIENT_PASS=pass
|
||||||
NGINX_PORT=8000
|
|
6
.gitignore
vendored
6
.gitignore
vendored
|
@ -10,9 +10,3 @@ Homestead.json
|
||||||
Homestead.yaml
|
Homestead.yaml
|
||||||
npm-debug.log
|
npm-debug.log
|
||||||
yarn-error.log
|
yarn-error.log
|
||||||
.idea
|
|
||||||
/resources/csv/exports/*.csv
|
|
||||||
/resources/csv/canastas/*.csv
|
|
||||||
/public/css/
|
|
||||||
/public/js/
|
|
||||||
/public/mix-manifest.json
|
|
||||||
|
|
|
@ -12,8 +12,7 @@ RUN apt-get update && apt-get install -y \
|
||||||
libonig-dev \
|
libonig-dev \
|
||||||
libxml2-dev \
|
libxml2-dev \
|
||||||
zip \
|
zip \
|
||||||
unzip \
|
unzip
|
||||||
npm
|
|
||||||
|
|
||||||
# Clear cache
|
# Clear cache
|
||||||
RUN apt-get clean && rm -rf /var/lib/apt/lists/*
|
RUN apt-get clean && rm -rf /var/lib/apt/lists/*
|
||||||
|
|
33
README.md
33
README.md
|
@ -1,6 +1,6 @@
|
||||||
# Pedi2
|
# Pedi2
|
||||||
|
|
||||||
Aplicación de pedidos del Mercado Popular de Subsistencia.
|
Aplicación de compras del Mercado Popular de Subsistencia.
|
||||||
|
|
||||||
Pedi2 está hecha en Laravel 7 y utiliza laravel7-docker de dyarleniber.
|
Pedi2 está hecha en Laravel 7 y utiliza laravel7-docker de dyarleniber.
|
||||||
|
|
||||||
|
@ -17,39 +17,41 @@ Se utilizan los siguientes servicios, separadamente:
|
||||||
## Instalación
|
## Instalación
|
||||||
1. Una vez descargado el proyecto, hacé una copia del archivo `.env.example` que se encuentra en la raíz del proyecto y nombrala `.env`. Seteá los valores correctos - específicamente, para las variables, `APP_URL`, `DB_USERNAME` y `DB_PASSWORD`. Prestá atención a que `DB_HOST` sea el nombre del servicio que corre MySQL (por defecto `DB_HOST=db`).
|
1. Una vez descargado el proyecto, hacé una copia del archivo `.env.example` que se encuentra en la raíz del proyecto y nombrala `.env`. Seteá los valores correctos - específicamente, para las variables, `APP_URL`, `DB_USERNAME` y `DB_PASSWORD`. Prestá atención a que `DB_HOST` sea el nombre del servicio que corre MySQL (por defecto `DB_HOST=db`).
|
||||||
|
|
||||||
2. Levantá los contenedores, construyendo la imagen de la app primero
|
2. Construí la imagen de la app
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
docker-compose up -d --build
|
docker-compose build app
|
||||||
|
```
|
||||||
|
|
||||||
|
3. Cuando termine, levantá los contenedores:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker-compose up -d
|
||||||
```
|
```
|
||||||
|
|
||||||
El ambiente ahora está andando, pero necesitamos ejecutar un par de comandos para terminar la instalación de Laravel. Podemos usar `docker-compose exec [nombre-del-servicio]` previo a un comando para ejecutarlo dentro del contenedor.
|
El ambiente ahora está andando, pero necesitamos ejecutar un par de comandos para terminar la instalación de Laravel. Podemos usar `docker-compose exec [nombre-del-servicio]` previo a un comando para ejecutarlo dentro del contenedor.
|
||||||
|
|
||||||
3. Terminá de instalar las dependencias de la app, según fueron definidas en `composer.json`.
|
4. Terminá de instalar las dependencias de la app, según fueron definidas en `composer.json`.
|
||||||
|
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
docker-compose exec app composer install
|
docker-compose exec app composer update
|
||||||
```
|
```
|
||||||
|
|
||||||
4. Generá una clave de aplicación. Esta clave se usa para encriptar datos sensibles.
|
5. Generá una clave de aplicación. Esta clave se usa para encriptar datos sensibles.
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
docker-compose exec app php artisan key:generate
|
docker-compose exec app php artisan key:generate
|
||||||
```
|
```
|
||||||
|
|
||||||
5. Corré las migraciones y seeders de Laravel
|
6. Corré las migraciones y seeders de Laravel
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
docker-compose exec app php artisan migrate:fresh --seed
|
docker-compose exec app php artisan migrate --seed
|
||||||
```
|
```
|
||||||
|
|
||||||
6. Copia el token que se imprime al correr los seeders. Lo necesitamos para autenticar las llamadas que hagamos desde nuestro cliente web
|
7. Copia el token que se imprime al correr los seeders. Lo necesitamos para autenticar las llamadas que hagamos desde nuestro cliente web
|
||||||
|
|
||||||
7. Instala las dependencias de npm
|
|
||||||
```bash
|
|
||||||
docker-compose exec app npm install
|
|
||||||
```
|
|
||||||
|
|
||||||
Ahora la aplicación está corriendo y la podés ver en el puerto 8000 de tu dominio o IP. En caso de que estés en tu máquina local, la vas a ver accediendo a `http://localhost:8000` desde tu navegador.
|
Ahora la aplicación está corriendo y la podés ver en el puerto 8000 de tu dominio o IP. En caso de que estés en tu máquina local, la vas a ver accediendo a `http://localhost:8000` desde tu navegador.
|
||||||
|
|
||||||
|
@ -59,11 +61,6 @@ Podés usar el comando `logs` para ver los logs generados por tus servicios:
|
||||||
docker-compose logs nginx
|
docker-compose logs nginx
|
||||||
```
|
```
|
||||||
|
|
||||||
8. Ejecuta npm para compilar el js y css
|
|
||||||
```bash
|
|
||||||
docker-compose exec app npm run prod
|
|
||||||
```
|
|
||||||
|
|
||||||
## Services description
|
## Services description
|
||||||
|
|
||||||
### Dockerfile
|
### Dockerfile
|
||||||
|
|
|
@ -1,11 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace App;
|
|
||||||
|
|
||||||
use Illuminate\Database\Eloquent\Model;
|
|
||||||
|
|
||||||
class CanastaLog extends Model
|
|
||||||
{
|
|
||||||
protected $fillable = ["path", "descripcion"];
|
|
||||||
protected $table = "carga_de_canastas";
|
|
||||||
}
|
|
|
@ -1,72 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Console\Commands;
|
|
||||||
|
|
||||||
use Illuminate\Console\Command;
|
|
||||||
use Illuminate\Support\Facades\DB;
|
|
||||||
|
|
||||||
class AgregarEsBonoAPedidosAprobados extends Command
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* The name and signature of the console command.
|
|
||||||
*
|
|
||||||
* @var string
|
|
||||||
*/
|
|
||||||
protected $signature = 'command:AgregarEsBonoAPedidosAprobados';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The console command description.
|
|
||||||
*
|
|
||||||
* @var string
|
|
||||||
*/
|
|
||||||
protected $description = 'Agrega "producto_bono" a la view PedidosAprobados';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a new command instance.
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
public function __construct()
|
|
||||||
{
|
|
||||||
parent::__construct();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Execute the console command.
|
|
||||||
*
|
|
||||||
* @return int
|
|
||||||
*/
|
|
||||||
public function handle(): int
|
|
||||||
{
|
|
||||||
DB::statement("
|
|
||||||
ALTER VIEW pedidos_aprobados(
|
|
||||||
grupo_de_compra_id,
|
|
||||||
grupo_de_compra_nombre,
|
|
||||||
grupo_de_compra_region,
|
|
||||||
producto_id,
|
|
||||||
producto_nombre,
|
|
||||||
producto_precio,
|
|
||||||
cantidad_pedida,
|
|
||||||
total_por_producto,
|
|
||||||
producto_es_bono
|
|
||||||
) AS
|
|
||||||
SELECT
|
|
||||||
g.id as grupo_de_compra_id,
|
|
||||||
g.nombre as grupo_de_compra_nombre,
|
|
||||||
g.region as grupo_de_compra_region,
|
|
||||||
pr.id AS producto_id,
|
|
||||||
pr.nombre as producto_nombre,
|
|
||||||
pr.precio as producto_precio,
|
|
||||||
SUM(ps.cantidad) as cantidad_pedida,
|
|
||||||
pr.precio*SUM(ps.cantidad) as total_por_producto,
|
|
||||||
pr.bono
|
|
||||||
FROM grupos_de_compra g
|
|
||||||
JOIN subpedidos s ON (s.grupo_de_compra_id = g.id AND s.aprobado=1)
|
|
||||||
JOIN producto_subpedido ps ON (ps.subpedido_id = s.id)
|
|
||||||
JOIN productos pr ON (pr.id = ps.producto_id)
|
|
||||||
GROUP BY
|
|
||||||
g.id, g.nombre, pr.id, pr.nombre
|
|
||||||
;");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,62 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Console\Commands;
|
|
||||||
|
|
||||||
use Illuminate\Console\Command;
|
|
||||||
use Illuminate\Support\Facades\DB;
|
|
||||||
|
|
||||||
class CrearPedidosAprobadosViewCommand extends Command
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* The name and signature of the console command.
|
|
||||||
*
|
|
||||||
* @var string
|
|
||||||
*/
|
|
||||||
protected $signature = 'view:CrearPedidosAprobadosView';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The console command description.
|
|
||||||
*
|
|
||||||
* @var string
|
|
||||||
*/
|
|
||||||
protected $description = 'Crea view "pedidos_aprobados"';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a new command instance.
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
public function __construct()
|
|
||||||
{
|
|
||||||
parent::__construct();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Execute the console command.
|
|
||||||
*
|
|
||||||
* @return int
|
|
||||||
*/
|
|
||||||
public function handle(): int
|
|
||||||
{
|
|
||||||
DB::statement("
|
|
||||||
CREATE OR REPLACE VIEW pedidos_aprobados
|
|
||||||
AS
|
|
||||||
SELECT
|
|
||||||
g.id as grupo_de_compra_id,
|
|
||||||
g.nombre as grupo_de_compra_nombre,
|
|
||||||
g.region as grupo_de_compra_region,
|
|
||||||
pr.id AS producto_id,
|
|
||||||
pr.nombre as producto_nombre,
|
|
||||||
pr.precio as producto_precio,
|
|
||||||
SUM(ps.cantidad) as cantidad_pedida,
|
|
||||||
pr.precio*SUM(ps.cantidad) as total_por_producto
|
|
||||||
FROM grupos_de_compra g
|
|
||||||
JOIN subpedidos s ON (s.grupo_de_compra_id = g.id AND s.aprobado=1)
|
|
||||||
JOIN producto_subpedido ps ON (ps.subpedido_id = s.id)
|
|
||||||
JOIN productos pr ON (pr.id = ps.producto_id)
|
|
||||||
GROUP BY
|
|
||||||
g.id, g.nombre, pr.id, pr.nombre
|
|
||||||
;");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -5,15 +5,12 @@ namespace App\Filtros;
|
||||||
use Illuminate\Database\Eloquent\Model;
|
use Illuminate\Database\Eloquent\Model;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
use Illuminate\Database\Eloquent\Builder;
|
use Illuminate\Database\Eloquent\Builder;
|
||||||
use Symfony\Component\HttpKernel\Exception\HttpException;
|
|
||||||
use Throwable;
|
|
||||||
use TypeError;
|
|
||||||
|
|
||||||
class Filtro extends Model
|
class Filtro extends Model
|
||||||
{
|
{
|
||||||
protected Request $request;
|
protected $request;
|
||||||
protected $builder;
|
protected $builder;
|
||||||
protected array $MENSAJES_ERROR = [
|
protected $MENSAJES_ERROR = [
|
||||||
'ARGUMENTO' => 'Argumento inválido para el parámetro %s. Revise la documentación.'
|
'ARGUMENTO' => 'Argumento inválido para el parámetro %s. Revise la documentación.'
|
||||||
];
|
];
|
||||||
|
|
||||||
|
@ -25,10 +22,10 @@ class Filtro extends Model
|
||||||
/**
|
/**
|
||||||
* Apply all existing filters, if available.
|
* Apply all existing filters, if available.
|
||||||
*
|
*
|
||||||
* @param Builder $builder
|
* @param \Illuminate\Database\Eloquent\Builder $builder
|
||||||
* @return Builder
|
* @return \Illuminate\Database\Eloquent\Builder
|
||||||
*/
|
*/
|
||||||
public function aplicar(Builder $builder): Builder
|
public function aplicar(Builder $builder)
|
||||||
{
|
{
|
||||||
$this->builder = $builder;
|
$this->builder = $builder;
|
||||||
|
|
||||||
|
@ -54,7 +51,7 @@ class Filtro extends Model
|
||||||
//Llamar métodos con argumentos
|
//Llamar métodos con argumentos
|
||||||
try {
|
try {
|
||||||
$this->$metodo($valor);
|
$this->$metodo($valor);
|
||||||
} catch (Throwable $th) {
|
} catch (\Throwable $th) {
|
||||||
if (is_a($th,'TypeError') ) { throw new HttpException(400, sprintf($this->MENSAJES_ERROR['ARGUMENTO'],$filtro)); }
|
if (is_a($th,'TypeError') ) { throw new HttpException(400, sprintf($this->MENSAJES_ERROR['ARGUMENTO'],$filtro)); }
|
||||||
throw $th;
|
throw $th;
|
||||||
}
|
}
|
||||||
|
@ -66,7 +63,7 @@ class Filtro extends Model
|
||||||
//Buscar un término en el nombre
|
//Buscar un término en el nombre
|
||||||
public function nombre(String $valor)
|
public function nombre(String $valor)
|
||||||
{
|
{
|
||||||
$this->builder->where('nombre', "LIKE", "%" . $valor . "%")->orderByRaw("IF(nombre = '$valor',2,IF(nombre LIKE '$valor%',1,0)) DESC");
|
$this->builder->where('nombre', "LIKE", "%" . $valor . "%")->orderByRaw("IF(nombre = '{$valor}',2,IF(nombre LIKE '{$valor}%',1,0)) DESC");
|
||||||
}
|
}
|
||||||
|
|
||||||
public function alfabetico(String $order = 'asc')
|
public function alfabetico(String $order = 'asc')
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace App\Filtros;
|
namespace App\Filtros;
|
||||||
|
use Illuminate\Database\Eloquent\Builder;
|
||||||
|
|
||||||
class FiltroDeProducto extends Filtro {
|
class FiltroDeProducto extends Filtro {
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
namespace App\Filtros;
|
namespace App\Filtros;
|
||||||
|
|
||||||
use TypeError;
|
use Illuminate\Database\Eloquent\Model;
|
||||||
|
|
||||||
class FiltroDeSubpedido extends Filtro
|
class FiltroDeSubpedido extends Filtro
|
||||||
{
|
{
|
||||||
|
|
|
@ -2,279 +2,17 @@
|
||||||
|
|
||||||
namespace App;
|
namespace App;
|
||||||
|
|
||||||
use App\Helpers\CsvHelper;
|
|
||||||
use App\Helpers\PdfHelper;
|
|
||||||
use App\Helpers\TransporteHelper;
|
|
||||||
use Illuminate\Database\Eloquent\Builder;
|
|
||||||
use Illuminate\Database\Eloquent\Model;
|
use Illuminate\Database\Eloquent\Model;
|
||||||
use Illuminate\Database\Eloquent\Relations\HasMany;
|
|
||||||
use Illuminate\Support\Collection;
|
|
||||||
use Illuminate\Support\Facades\DB;
|
|
||||||
use Illuminate\Support\Facades\Log;
|
|
||||||
|
|
||||||
class GrupoDeCompra extends Model
|
class GrupoDeCompra extends Model
|
||||||
{
|
{
|
||||||
public $timestamps = false;
|
public $timestamps = false;
|
||||||
protected $fillable = ["nombre", "region", "telefono", "correo", "referente_finanzas", "cantidad_de_nucleos", "fila", "devoluciones_habilitadas"];
|
protected $fillable = [ "nombre","region","telefono","correo","referente_finanzas","cantidad_de_nucleos"];
|
||||||
protected $table = 'grupos_de_compra';
|
protected $table = 'grupos_de_compra';
|
||||||
protected $hidden = ['password'];
|
protected $hidden = ['password'];
|
||||||
|
|
||||||
public function subpedidos(): HasMany
|
public function subpedidos() {
|
||||||
{
|
return $this->hasMany('App\Subpedido');
|
||||||
return $this->hasMany(Subpedido::class);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function toggleDevoluciones(): bool
|
|
||||||
{
|
|
||||||
$this->devoluciones_habilitadas = !$this->devoluciones_habilitadas;
|
|
||||||
$this->save();
|
|
||||||
return $this->devoluciones_habilitadas;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function pedidosAprobados()
|
|
||||||
{
|
|
||||||
return $this->subpedidos->where('aprobado', 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function totalARecaudar()
|
|
||||||
{
|
|
||||||
$total = 0;
|
|
||||||
foreach ($this->pedidosAprobados() as $subpedido) {
|
|
||||||
$total = $total + $subpedido->total();
|
|
||||||
}
|
|
||||||
return $total;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function totalBarrial()
|
|
||||||
{
|
|
||||||
$total = 0;
|
|
||||||
foreach ($this->pedidosAprobados() as $subpedido) {
|
|
||||||
$total = $total + $subpedido->totalBarrial();
|
|
||||||
}
|
|
||||||
return $total;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function totalDevoluciones()
|
|
||||||
{
|
|
||||||
$total = 0;
|
|
||||||
foreach ($this->pedidosAprobados() as $subpedido) {
|
|
||||||
$total = $total + $subpedido->devoluciones_total;
|
|
||||||
}
|
|
||||||
return $total;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function totalATransferir()
|
|
||||||
{
|
|
||||||
return $this->totalCentralesQueNoPaganTransporte()
|
|
||||||
+ $this->totalCentralesQuePaganTransporte()
|
|
||||||
+ $this->totalTransporte();
|
|
||||||
}
|
|
||||||
|
|
||||||
public function totalCentralesQueNoPaganTransporte()
|
|
||||||
{
|
|
||||||
$total = 0;
|
|
||||||
foreach ($this->pedidosAprobados() as $subpedido) {
|
|
||||||
$total = $total + $subpedido->totalCentralesQueNoPaganTransporte();
|
|
||||||
}
|
|
||||||
return $total;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function totalCentralesQuePaganTransporte()
|
|
||||||
{
|
|
||||||
$total = 0;
|
|
||||||
foreach ($this->pedidosAprobados() as $subpedido) {
|
|
||||||
$total = $total + $subpedido->totalCentralesQuePaganTransporte();
|
|
||||||
}
|
|
||||||
return $total;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function totalTransporte()
|
|
||||||
{
|
|
||||||
return TransporteHelper::totalTransporte($this->totalCentralesQuePaganTransporte());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return int
|
|
||||||
* Calcula la cantidad de bonos de transporte del barrio
|
|
||||||
*/
|
|
||||||
public function cantidadTransporte(): int
|
|
||||||
{
|
|
||||||
return TransporteHelper::cantidadTransporte($this->totalCentralesQuePaganTransporte());
|
|
||||||
}
|
|
||||||
|
|
||||||
public function exportarPedidosAPdf()
|
|
||||||
{
|
|
||||||
$subpedidos = $this->pedidosAprobados();
|
|
||||||
PdfHelper::exportarPedidos($this->nombre . '.pdf', $subpedidos);
|
|
||||||
}
|
|
||||||
|
|
||||||
function pedidoParaPdf(): array
|
|
||||||
{
|
|
||||||
$productos = $this->productosPedidos(true, true);
|
|
||||||
$pedido = [];
|
|
||||||
$pedido['productos'] = [];
|
|
||||||
|
|
||||||
$pedido['nombre'] = $this->nombre;
|
|
||||||
foreach ($productos as $producto) {
|
|
||||||
$productoParaPdf = [];
|
|
||||||
$productoParaPdf['pivot'] = [];
|
|
||||||
$productoParaPdf['nombre'] = $producto->producto_nombre;
|
|
||||||
$productoParaPdf['pivot']['cantidad'] = $producto->cantidad_pedida;
|
|
||||||
$productoParaPdf['pivot']['notas'] = false;
|
|
||||||
$productoParaPdf['bono'] = $producto->producto_es_bono;
|
|
||||||
|
|
||||||
$pedido['productos'][] = $productoParaPdf;
|
|
||||||
}
|
|
||||||
|
|
||||||
return $pedido;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function generarHTML()
|
|
||||||
{
|
|
||||||
$view = view("pdfgen.pedido_tabla", ["pedido" => $this->pedidoParaPdf()]);
|
|
||||||
return $view->render();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function exportarPedidosBarrialesAPdf()
|
|
||||||
{
|
|
||||||
$barrios = GrupoDeCompra::barriosMenosPrueba()->get();
|
|
||||||
PdfHelper::exportarPedidos('pedidos_por_barrio.pdf', $barrios);
|
|
||||||
}
|
|
||||||
|
|
||||||
static function filaVacia(string $product, int $columns): array
|
|
||||||
{
|
|
||||||
$fila = [$product];
|
|
||||||
for ($i = 1; $i <= $columns; $i++) {
|
|
||||||
$fila[$i] = "0";
|
|
||||||
}
|
|
||||||
return $fila;
|
|
||||||
}
|
|
||||||
|
|
||||||
//Asume que los productos están gruadados en orden de fila
|
|
||||||
public static function obtenerTemplateDeFilasVacias(int $columns): array
|
|
||||||
{
|
|
||||||
$productosFilaID = Producto::productosFilaID();
|
|
||||||
$productosIDNombre = Producto::productosIDNombre();
|
|
||||||
$num_fila = 1;
|
|
||||||
$template = [];
|
|
||||||
foreach ($productosFilaID as $fila => $id) {
|
|
||||||
for ($i = $num_fila; $i < $fila; $i++) {
|
|
||||||
$template[$i] = GrupoDeCompra::filaVacia("", $columns);
|
|
||||||
}
|
|
||||||
$template[$fila] = GrupoDeCompra::filaVacia($productosIDNombre[$id], $columns);
|
|
||||||
$num_fila = $fila + 1;
|
|
||||||
}
|
|
||||||
$template[TransporteHelper::filaTransporte()] = GrupoDeCompra::filaVacia("Bonos de transporte", $columns);
|
|
||||||
return $template;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function exportarPedidoEnCSV()
|
|
||||||
{
|
|
||||||
$records = $this->generarColumnaCantidades();
|
|
||||||
|
|
||||||
CsvHelper::generarCsv('csv/exports/' . $this->nombre . '.csv', $records);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function generarColumnaCantidades(): array
|
|
||||||
{
|
|
||||||
$productos_en_pedido = $this->productosPedidos();
|
|
||||||
|
|
||||||
//si no hay pedidos aprobados, salir
|
|
||||||
if ($productos_en_pedido->count() == 0) {
|
|
||||||
Log::debug("El grupo de compra " . $this->nombre . " no tiene pedidos aprobados.");
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
|
|
||||||
$records = $this->obtenerTemplateDeFilasVacias(1);
|
|
||||||
$productos_id_fila = Producto::productosIDFila();
|
|
||||||
foreach ($productos_en_pedido as $id => $producto_pedido) {
|
|
||||||
$fila = $productos_id_fila[$id];
|
|
||||||
$records[$fila][1] = $producto_pedido->cantidad_pedida;
|
|
||||||
}
|
|
||||||
|
|
||||||
$records[TransporteHelper::filaTransporte()][1] = $this->cantidadTransporte();
|
|
||||||
|
|
||||||
return $records;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function exportarPedidoConNucleosEnCSV()
|
|
||||||
{
|
|
||||||
$productos_en_pedido = $this->productosPedidos();
|
|
||||||
|
|
||||||
// si no hay pedidos aprobados, salir
|
|
||||||
if ($productos_en_pedido->count() == 0) {
|
|
||||||
Log::debug("El grupo de compra " . $this->nombre . " no tiene pedidos aprobados.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
$pedidos = $this->pedidosAprobados();
|
|
||||||
// Generar tabla vacía con una columna por núcleo
|
|
||||||
$records = $this->obtenerTemplateDeFilasVacias($pedidos->count());
|
|
||||||
$productos_id_fila = Producto::productosIDFila();
|
|
||||||
|
|
||||||
foreach ($productos_en_pedido as $id => $producto_pedido) {
|
|
||||||
$fila = $productos_id_fila[$id];
|
|
||||||
$i = 1;
|
|
||||||
// Poner cantidad de cada producto para cada núcleo
|
|
||||||
foreach ($pedidos as $pedido) {
|
|
||||||
list($records, $i, $_) = $this->agregarCantidad($pedido, $id, $records, $fila, $i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Insertar lista de núcleos en la primera fila
|
|
||||||
$nucleos = [""];
|
|
||||||
$i = 1;
|
|
||||||
foreach ($pedidos as $pedido) {
|
|
||||||
$nucleos[$i] = $pedido->nombre;
|
|
||||||
$i++;
|
|
||||||
}
|
|
||||||
array_splice($records, 0, 0, array($nucleos));
|
|
||||||
|
|
||||||
CsvHelper::generarCsv('csv/exports/' . $this->nombre . '-completo.csv', $records);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function agregarCantidad($pedido, $id, array $records, $fila, int $i): array
|
|
||||||
{
|
|
||||||
$producto = $pedido->productos()->find($id);
|
|
||||||
$cantidad = $producto == NULL ? 0 : $producto->pivot->cantidad;
|
|
||||||
$records[$fila][$i] = $cantidad;
|
|
||||||
$i++;
|
|
||||||
return array($records, $i, $cantidad);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function barriosMenosPrueba(): Builder
|
|
||||||
{
|
|
||||||
return self::where('nombre', '<>', 'PRUEBA')
|
|
||||||
->orderBy('region')
|
|
||||||
->orderBy('nombre');
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function transportePorBarrio(): array
|
|
||||||
{
|
|
||||||
$result = [];
|
|
||||||
$barrios = GrupoDeCompra::barriosMenosPrueba()->get();
|
|
||||||
|
|
||||||
foreach ($barrios as $barrio) {
|
|
||||||
$result[] = $barrio->cantidadTransporte();
|
|
||||||
}
|
|
||||||
|
|
||||||
return $result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return Collection
|
|
||||||
*/
|
|
||||||
public function productosPedidos($excluirBarriales = false, $excluirBonos = false): Collection
|
|
||||||
{
|
|
||||||
$query = DB::table('pedidos_aprobados')
|
|
||||||
->where('grupo_de_compra_id', $this->id);
|
|
||||||
|
|
||||||
if ($excluirBarriales)
|
|
||||||
$query = $query->where('producto_nombre','NOT LIKE','%barrial%');
|
|
||||||
if ($excluirBonos)
|
|
||||||
$query = $query->where('producto_es_bono',false);
|
|
||||||
|
|
||||||
return $query
|
|
||||||
->get()
|
|
||||||
->keyBy('producto_id');
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,146 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Helpers;
|
|
||||||
|
|
||||||
use App\Producto;
|
|
||||||
use App\Proveedor;
|
|
||||||
use App\CanastaLog;
|
|
||||||
use DatabaseSeeder;
|
|
||||||
use Illuminate\Support\Arr;
|
|
||||||
use Illuminate\Support\Facades\DB;
|
|
||||||
use Illuminate\Support\Str;
|
|
||||||
|
|
||||||
|
|
||||||
class CanastaHelper
|
|
||||||
{
|
|
||||||
const TIPO = "Tipo";
|
|
||||||
const TOTAL = "TOTAL";
|
|
||||||
const ARCHIVO_SUBIDO = 'Archivo subido';
|
|
||||||
const CANASTA_CARGADA = 'Canasta cargada';
|
|
||||||
const TIPOS_BONO = ["B", "F", "BE"];
|
|
||||||
|
|
||||||
public static function guardarCanasta($data, $path): string {
|
|
||||||
$nombre = $data->getClientOriginalName();
|
|
||||||
|
|
||||||
$data->move(resource_path($path), $nombre);
|
|
||||||
|
|
||||||
self::log($path . $nombre, self::ARCHIVO_SUBIDO);
|
|
||||||
|
|
||||||
return $nombre;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function cargarCanasta($archivo) {
|
|
||||||
self::limpiarTablas();
|
|
||||||
|
|
||||||
$registros = CsvHelper::getRecords($archivo);
|
|
||||||
$toInsert = [];
|
|
||||||
$categoria = '';
|
|
||||||
|
|
||||||
foreach($registros as $i => $registro) {
|
|
||||||
// finalizar
|
|
||||||
if ($registro[self::TIPO] == self::TOTAL)
|
|
||||||
break;
|
|
||||||
|
|
||||||
// saltear filas que no tienen tipo
|
|
||||||
if (self::noTieneTipo($registro)) {
|
|
||||||
var_dump("no hay tipo en la fila " . $i);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// saltear bono de transporte
|
|
||||||
if ($registro[self::TIPO] == "T"){
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// obtener categoria si no hay producto
|
|
||||||
if ($registro['Producto'] == '') {
|
|
||||||
// no es la pregunta de la copa?
|
|
||||||
if (!Str::contains($registro[self::TIPO],"¿"))
|
|
||||||
$categoria = $registro[self::TIPO];
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// completar producto
|
|
||||||
$toInsert[] = [
|
|
||||||
'fila' => $i,
|
|
||||||
'categoria' => $categoria,
|
|
||||||
'nombre' => trim(str_replace('*', '',$registro['Producto'])),
|
|
||||||
'precio' => $registro['Precio'],
|
|
||||||
'proveedor_id' => self::obtenerProveedor($registro['Producto']),
|
|
||||||
'bono' => in_array($registro[self::TIPO], self::TIPOS_BONO),
|
|
||||||
'requiere_notas'=> $registro[self::TIPO] =="PTC",
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (array_chunk($toInsert,DatabaseSeeder::CHUNK_SIZE) as $chunk) {
|
|
||||||
DB::table('productos')->insert($chunk);
|
|
||||||
}
|
|
||||||
|
|
||||||
self::agregarBonoBarrial();
|
|
||||||
|
|
||||||
self::log($archivo, self::CANASTA_CARGADA);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static function obtenerProveedor($nombre) {
|
|
||||||
$result = null;
|
|
||||||
if (Str::contains($nombre,"*")){
|
|
||||||
$result = Proveedor::firstOrCreate([
|
|
||||||
'nombre' => 'Proveedor de economía solidaria',
|
|
||||||
'economia_solidaria' => 1,
|
|
||||||
'nacional' => 1
|
|
||||||
])->id;
|
|
||||||
}
|
|
||||||
return $result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param $path
|
|
||||||
* @param $descripcion
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
private static function log($path, $descripcion): void
|
|
||||||
{
|
|
||||||
$log = new CanastaLog([
|
|
||||||
'path' => $path,
|
|
||||||
'descripcion' => $descripcion,
|
|
||||||
]);
|
|
||||||
$log->save();
|
|
||||||
}
|
|
||||||
|
|
||||||
private static function limpiarTablas()
|
|
||||||
{
|
|
||||||
DB::delete('delete from producto_subpedido');
|
|
||||||
DB::delete('delete from productos');
|
|
||||||
DB::delete('delete from subpedidos');
|
|
||||||
}
|
|
||||||
|
|
||||||
private static function agregarBonoBarrial()
|
|
||||||
{
|
|
||||||
$categoria = Producto::all()
|
|
||||||
->pluck('categoria')
|
|
||||||
->unique()
|
|
||||||
->flatten()
|
|
||||||
->first(function ($c) {
|
|
||||||
return Str::contains($c, 'BONO');
|
|
||||||
});
|
|
||||||
|
|
||||||
DB::table('productos')->insert([
|
|
||||||
'fila' => 420,
|
|
||||||
'nombre' => "Bono barrial",
|
|
||||||
'precio' => 20,
|
|
||||||
'categoria' => $categoria,
|
|
||||||
'bono' => 1,
|
|
||||||
'proveedor_id' => null,
|
|
||||||
'requiere_notas'=> false,
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param $registro
|
|
||||||
* @return bool
|
|
||||||
*/
|
|
||||||
public static function noTieneTipo($registro): bool
|
|
||||||
{
|
|
||||||
return !Arr::has($registro, self::TIPO) || trim($registro[self::TIPO]) == '';
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,40 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Helpers;
|
|
||||||
|
|
||||||
use Illuminate\Support\Facades\Log;
|
|
||||||
use Iterator;
|
|
||||||
use League\Csv\CannotInsertRecord;
|
|
||||||
use League\Csv\Exception;
|
|
||||||
use League\Csv\InvalidArgument;
|
|
||||||
use League\Csv\Reader;
|
|
||||||
use League\Csv\Writer;
|
|
||||||
|
|
||||||
class CsvHelper
|
|
||||||
{
|
|
||||||
public static function getRecords($filePath): Iterator {
|
|
||||||
$csv = Reader::createFromPath(resource_path($filePath));
|
|
||||||
try {
|
|
||||||
$csv->setDelimiter("|");
|
|
||||||
$csv->setEnclosure("'");
|
|
||||||
$csv->setHeaderOffset(0);
|
|
||||||
return $csv->getRecords();
|
|
||||||
} catch (InvalidArgument|Exception $e) {
|
|
||||||
Log::error($e->getMessage());
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function generarCsv($filePath, $contenido, $headers = null): void
|
|
||||||
{
|
|
||||||
try {
|
|
||||||
$writer = Writer::createFromPath(resource_path($filePath), 'w');
|
|
||||||
if ($headers) {
|
|
||||||
$writer->insertOne($headers);
|
|
||||||
}
|
|
||||||
$writer->insertAll($contenido);
|
|
||||||
} catch (CannotInsertRecord $e) {
|
|
||||||
Log::error($e->getMessage(), $e->getTrace());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,29 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Helpers;
|
|
||||||
|
|
||||||
use Mpdf\Mpdf;
|
|
||||||
use Mpdf\MpdfException;
|
|
||||||
|
|
||||||
class PdfHelper
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Requiere que el segundo argumento tenga definida la función generarHTML()
|
|
||||||
* para crear la tabla con los datos del pedido que se inserta en el pdf.
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
* @throws MpdfException
|
|
||||||
*/
|
|
||||||
public static function exportarPedidos($filepath, $pedidos)
|
|
||||||
{
|
|
||||||
$mpdf = new Mpdf();
|
|
||||||
|
|
||||||
foreach ($pedidos as $pedido) {
|
|
||||||
$html = $pedido->generarHTML();
|
|
||||||
$mpdf->WriteHTML($html);
|
|
||||||
$mpdf->AddPage();
|
|
||||||
}
|
|
||||||
|
|
||||||
$mpdf->Output($filepath, 'D');
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,38 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Helpers;
|
|
||||||
|
|
||||||
use App\CanastaLog;
|
|
||||||
use Illuminate\Support\Facades\Log;
|
|
||||||
|
|
||||||
class TransporteHelper
|
|
||||||
{
|
|
||||||
const COSTO_TRANSPORTE = 15;
|
|
||||||
const MONTO_TRANSPORTE = 500;
|
|
||||||
|
|
||||||
public static function cantidadTransporte($monto)
|
|
||||||
{
|
|
||||||
return ceil($monto / self::MONTO_TRANSPORTE);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function totalTransporte($monto)
|
|
||||||
{
|
|
||||||
return self::cantidadTransporte($monto) * self::COSTO_TRANSPORTE;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function filaTransporte()
|
|
||||||
{
|
|
||||||
$ultimaCanasta = CanastaLog::where('descripcion', CanastaHelper::CANASTA_CARGADA)
|
|
||||||
->orderBy('created_at', 'desc')
|
|
||||||
->pluck('path')
|
|
||||||
->first();
|
|
||||||
|
|
||||||
$registros = CsvHelper::getRecords($ultimaCanasta);
|
|
||||||
|
|
||||||
foreach ($registros as $key => $registro)
|
|
||||||
if ($registro[CanastaHelper::TIPO] == 'T') return $key;
|
|
||||||
|
|
||||||
Log::error('No hay fila de tipo T en la planilla: ' . $ultimaCanasta);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -2,35 +2,9 @@
|
||||||
|
|
||||||
namespace App\Http\Controllers;
|
namespace App\Http\Controllers;
|
||||||
|
|
||||||
use App\GrupoDeCompra;
|
use Illuminate\Http\Request;
|
||||||
use Symfony\Component\HttpFoundation\BinaryFileResponse;
|
|
||||||
|
|
||||||
class AdminController extends Controller
|
class AdminController extends Controller
|
||||||
{
|
{
|
||||||
public function show()
|
//
|
||||||
{
|
|
||||||
return view('auth/admin_login');
|
|
||||||
}
|
|
||||||
|
|
||||||
public function index() {
|
|
||||||
return view('auth/admin_subpedidos');
|
|
||||||
}
|
|
||||||
|
|
||||||
public function exportarPedidosAPdf(GrupoDeCompra $gdc) {
|
|
||||||
$gdc->exportarPedidosAPdf();
|
|
||||||
}
|
|
||||||
|
|
||||||
public function exportarPedidoACSV(GrupoDeCompra $gdc): BinaryFileResponse
|
|
||||||
{
|
|
||||||
$gdc->exportarPedidoEnCSV();
|
|
||||||
$file = resource_path('csv/exports/'.$gdc->nombre.'.csv');
|
|
||||||
return response()->download($file);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function exportarPedidoConNucleosACSV(GrupoDeCompra $gdc): BinaryFileResponse
|
|
||||||
{
|
|
||||||
$gdc->exportarPedidoConNucleosEnCSV();
|
|
||||||
$file = resource_path('csv/exports/'.$gdc->nombre.'-completo.csv');
|
|
||||||
return response()->download($file);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,19 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Http\Controllers\Api;
|
|
||||||
|
|
||||||
use App\GrupoDeCompra;
|
|
||||||
use App\Http\Controllers\Controller;
|
|
||||||
use App\Http\Resources\GrupoDeCompraResource;
|
|
||||||
|
|
||||||
class GrupoDeCompraController extends Controller
|
|
||||||
{
|
|
||||||
public function index()
|
|
||||||
{
|
|
||||||
return GrupoDeCompraResource::collection(GrupoDeCompra::all());
|
|
||||||
}
|
|
||||||
public function show(GrupoDeCompra $grupoDeCompra)
|
|
||||||
{
|
|
||||||
return new GrupoDeCompraResource($grupoDeCompra);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -10,11 +10,24 @@ use App\Producto;
|
||||||
|
|
||||||
class ProductoController extends Controller
|
class ProductoController extends Controller
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* Mostrar una lista de productos.
|
||||||
|
*
|
||||||
|
* @param App\Filtros\FiltroDeProducto $filtros
|
||||||
|
* @param \Illuminate\Http\Request $request
|
||||||
|
* @return \Illuminate\Http\Response
|
||||||
|
*/
|
||||||
public function index(FiltroDeProducto $filtros, Request $request)
|
public function index(FiltroDeProducto $filtros, Request $request)
|
||||||
{
|
{
|
||||||
return ProductoResource::collection(Producto::filtrar($filtros)->paginate(Producto::getPaginar($request)));
|
return ProductoResource::collection(Producto::filtrar($filtros)->paginate(Producto::getPaginar($request)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Display the specified resource.
|
||||||
|
*
|
||||||
|
* @param \App\Producto $producto
|
||||||
|
* @return \Illuminate\Http\Response
|
||||||
|
*/
|
||||||
public function show(Producto $producto)
|
public function show(Producto $producto)
|
||||||
{
|
{
|
||||||
return new ProductoResource($producto);
|
return new ProductoResource($producto);
|
||||||
|
|
|
@ -3,28 +3,35 @@
|
||||||
namespace App\Http\Controllers\Api;
|
namespace App\Http\Controllers\Api;
|
||||||
|
|
||||||
use App\Http\Controllers\Controller;
|
use App\Http\Controllers\Controller;
|
||||||
use App\Producto;
|
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
use App\Filtros\FiltroDeSubpedido;
|
use App\Filtros\FiltroDeSubpedido;
|
||||||
use App\Subpedido;
|
use App\Subpedido;
|
||||||
use App\GrupoDeCompra;
|
use App\GrupoDeCompra;
|
||||||
use App\Http\Resources\SubpedidoResource;
|
use App\Producto;
|
||||||
use Illuminate\Validation\Rule;
|
use Illuminate\Validation\Rule;
|
||||||
use Symfony\Component\HttpKernel\Exception\HttpException;
|
use Symfony\Component\HttpKernel\Exception\HttpException;
|
||||||
|
|
||||||
|
|
||||||
class SubpedidoController extends Controller
|
class SubpedidoController extends Controller
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* Mostrar una lista de productos.
|
||||||
|
*
|
||||||
|
* @param App\Filtros\FiltroDeSubpedido $filtros
|
||||||
|
* @param \Illuminate\Http\Request $request
|
||||||
|
* @return \Illuminate\Http\Response
|
||||||
|
*/
|
||||||
public function index(FiltroDeSubpedido $filtros, Request $request)
|
public function index(FiltroDeSubpedido $filtros, Request $request)
|
||||||
{
|
{
|
||||||
return Subpedido::filtrar($filtros)->get();
|
return Subpedido::filtrar($filtros)->get();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function indexResources(FiltroDeSubpedido $filtros, Request $request)
|
/**
|
||||||
{
|
* Guardar un nuevo registro en el almacenamiento.
|
||||||
return SubpedidoResource::collection(Subpedido::filtrar($filtros)->get());
|
*
|
||||||
}
|
* @param \Illuminate\Http\Request $request
|
||||||
|
* @return \Illuminate\Http\Response
|
||||||
|
*/
|
||||||
public function store(Request $request)
|
public function store(Request $request)
|
||||||
{
|
{
|
||||||
$validado = $this->validateSubpedido();
|
$validado = $this->validateSubpedido();
|
||||||
|
@ -38,8 +45,29 @@ class SubpedidoController extends Controller
|
||||||
return $s;
|
return $s;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function validateSubpedido(): array
|
/**
|
||||||
|
* Agregar un producto a un subpedido.
|
||||||
|
*
|
||||||
|
* @param \Illuminate\Http\Request $request
|
||||||
|
* @return \Illuminate\Http\Response
|
||||||
|
*/
|
||||||
|
public function updateProducto(Subpedido $subpedido, Producto $producto, Request $request)
|
||||||
{
|
{
|
||||||
|
$validado = $this->validateActualizacionDeProducto();
|
||||||
|
$cantidad = $validado['cantidad'];
|
||||||
|
|
||||||
|
if ($cantidad){
|
||||||
|
//si la cantidad es 1 o más se agrega el producto o actualiza la cantidad
|
||||||
|
$subpedido->productos()->syncWithoutDetaching([$producto->id => ['cantidad' => $cantidad]]);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
//si la cantidad es 0, se elimina el producto del subpedido
|
||||||
|
$subpedido->productos()->detach($producto->id);
|
||||||
|
}
|
||||||
|
return response('Producto ' . $producto->nombre . ' actualizado en subpedido de ' . $subpedido->nombre . ' (cantidad ' . $cantidad . ')', 200);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function validateSubpedido(){
|
||||||
return request()->validate([
|
return request()->validate([
|
||||||
'nombre' => 'required|max:255',
|
'nombre' => 'required|max:255',
|
||||||
'grupo_de_compra_id' => [
|
'grupo_de_compra_id' => [
|
||||||
|
@ -49,49 +77,9 @@ class SubpedidoController extends Controller
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function show(Subpedido $subpedido)
|
protected function validateActualizacionDeProducto(){
|
||||||
{
|
return request()->validate([
|
||||||
return new SubpedidoResource($subpedido);
|
'cantidad' => 'required|min:0'
|
||||||
}
|
|
||||||
|
|
||||||
// recibe request, saca producto y cantidad, valida, y pasa a syncProducto en Subpedido
|
|
||||||
public function syncProductos(Subpedido $subpedido) {
|
|
||||||
if ($subpedido->aprobado)
|
|
||||||
return new SubpedidoResource($subpedido);
|
|
||||||
|
|
||||||
$valid = request()->validate([
|
|
||||||
'cantidad' => ['integer','required','min:0'],
|
|
||||||
'notas' => 'nullable',
|
|
||||||
'producto_id' => [
|
|
||||||
'required',
|
|
||||||
Rule::in(Producto::all()->pluck('id')),
|
|
||||||
]
|
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$producto = Producto::find($valid['producto_id']);
|
|
||||||
$notas = $valid['notas'];
|
|
||||||
$cantidad = $valid['cantidad'];
|
|
||||||
$subpedido->syncProducto($producto, $cantidad, $notas ?? "");
|
|
||||||
return new SubpedidoResource($subpedido);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function toggleAprobacion(Subpedido $subpedido) {
|
|
||||||
$valid = request()->validate([
|
|
||||||
'aprobacion' => 'required | boolean'
|
|
||||||
]);
|
|
||||||
$subpedido->toggleAprobacion($valid['aprobacion']);
|
|
||||||
return new SubpedidoResource($subpedido);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function syncDevoluciones(Subpedido $subpedido) {
|
|
||||||
if ($subpedido->aprobado) return new SubpedidoResource($subpedido);
|
|
||||||
|
|
||||||
$valid = request()->validate([
|
|
||||||
'total' => 'required|min:0',
|
|
||||||
'notas' => 'min:0'
|
|
||||||
]);
|
|
||||||
$subpedido->syncDevoluciones($valid['total'], $valid['notas'] ?? "");
|
|
||||||
|
|
||||||
return new SubpedidoResource($subpedido);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,6 @@ namespace App\Http\Controllers\Auth;
|
||||||
use App\Http\Controllers\Controller;
|
use App\Http\Controllers\Controller;
|
||||||
use App\Providers\RouteServiceProvider;
|
use App\Providers\RouteServiceProvider;
|
||||||
use Illuminate\Foundation\Auth\AuthenticatesUsers;
|
use Illuminate\Foundation\Auth\AuthenticatesUsers;
|
||||||
use Illuminate\Http\Request;
|
|
||||||
use Illuminate\Support\Facades\Auth;
|
use Illuminate\Support\Facades\Auth;
|
||||||
|
|
||||||
class LoginController extends Controller
|
class LoginController extends Controller
|
||||||
|
@ -29,18 +28,6 @@ class LoginController extends Controller
|
||||||
*/
|
*/
|
||||||
protected $redirectTo = RouteServiceProvider::HOME;
|
protected $redirectTo = RouteServiceProvider::HOME;
|
||||||
|
|
||||||
protected function authenticated(Request $request, $user)
|
|
||||||
{
|
|
||||||
if ($user->is_compras) {
|
|
||||||
return redirect('compras/pedidos');
|
|
||||||
} else if ($user->is_admin) {
|
|
||||||
session(['admin_gdc' => $user->grupo_de_compra_id]);
|
|
||||||
return redirect('admin/pedidos');
|
|
||||||
} else {
|
|
||||||
return redirect('/');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new controller instance.
|
* Create a new controller instance.
|
||||||
*
|
*
|
||||||
|
|
|
@ -1,62 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Http\Controllers;
|
|
||||||
|
|
||||||
use App\GrupoDeCompra;
|
|
||||||
use App\Helpers\CanastaHelper;
|
|
||||||
use App\Producto;
|
|
||||||
use Illuminate\Http\JsonResponse;
|
|
||||||
use Illuminate\Http\Request;
|
|
||||||
use Symfony\Component\HttpFoundation\BinaryFileResponse;
|
|
||||||
|
|
||||||
class ComprasController
|
|
||||||
{
|
|
||||||
const CANASTAS_PATH = 'csv/canastas/';
|
|
||||||
|
|
||||||
public function indexPedidos() {
|
|
||||||
return view('compras_pedidos');
|
|
||||||
}
|
|
||||||
|
|
||||||
public function descargarPedidos(): BinaryFileResponse
|
|
||||||
{
|
|
||||||
Producto::planillaTotales();
|
|
||||||
$file = resource_path('csv/exports/pedidos-por-barrio.csv');
|
|
||||||
return response()->download($file);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function descargarNotas(): BinaryFileResponse
|
|
||||||
{
|
|
||||||
Producto::planillaNotas();
|
|
||||||
$file = resource_path('csv/exports/notas-por-barrio.csv');
|
|
||||||
return response()->download($file);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function pdf() {
|
|
||||||
GrupoDeCompra::exportarPedidosBarrialesAPdf();
|
|
||||||
}
|
|
||||||
|
|
||||||
public function show()
|
|
||||||
{
|
|
||||||
return view('auth/compras_login');
|
|
||||||
}
|
|
||||||
|
|
||||||
public function cargarCanasta(Request $request): JsonResponse
|
|
||||||
{
|
|
||||||
$request->validate([
|
|
||||||
'data' => 'required|file|mimes:csv,txt|max:2048',
|
|
||||||
]);
|
|
||||||
|
|
||||||
$nombre = CanastaHelper::guardarCanasta($request->file('data'), self::CANASTAS_PATH);
|
|
||||||
CanastaHelper::cargarCanasta(self::CANASTAS_PATH . $nombre);
|
|
||||||
|
|
||||||
return response()->json([
|
|
||||||
'message' => 'Canasta cargada exitosamente',
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function descargarCanastaEjemplo(): BinaryFileResponse
|
|
||||||
{
|
|
||||||
$file = resource_path('csv/productos.csv');
|
|
||||||
return response()->download($file);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -2,6 +2,8 @@
|
||||||
|
|
||||||
namespace App\Http\Controllers;
|
namespace App\Http\Controllers;
|
||||||
|
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
|
||||||
class ProductoController extends Controller
|
class ProductoController extends Controller
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
|
@ -14,6 +16,11 @@ class ProductoController extends Controller
|
||||||
$this->middleware(['auth','subpedido']);
|
$this->middleware(['auth','subpedido']);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Show the application dashboard.
|
||||||
|
*
|
||||||
|
* @return \Illuminate\Contracts\Support\Renderable
|
||||||
|
*/
|
||||||
public function index()
|
public function index()
|
||||||
{
|
{
|
||||||
return view('productos');
|
return view('productos');
|
||||||
|
|
|
@ -56,8 +56,6 @@ class Kernel extends HttpKernel
|
||||||
*/
|
*/
|
||||||
protected $routeMiddleware = [
|
protected $routeMiddleware = [
|
||||||
'auth' => \App\Http\Middleware\Authenticate::class,
|
'auth' => \App\Http\Middleware\Authenticate::class,
|
||||||
'admin' => \App\Http\Middleware\Admin::class,
|
|
||||||
'compras' => \App\Http\Middleware\Compras::class,
|
|
||||||
'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
|
'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
|
||||||
'bindings' => \Illuminate\Routing\Middleware\SubstituteBindings::class,
|
'bindings' => \Illuminate\Routing\Middleware\SubstituteBindings::class,
|
||||||
'cache.headers' => \Illuminate\Http\Middleware\SetCacheHeaders::class,
|
'cache.headers' => \Illuminate\Http\Middleware\SetCacheHeaders::class,
|
||||||
|
|
|
@ -1,20 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Http\Middleware;
|
|
||||||
|
|
||||||
use Closure;
|
|
||||||
use Illuminate\Support\Facades\Auth;
|
|
||||||
use Illuminate\Http\Request;
|
|
||||||
|
|
||||||
class Admin
|
|
||||||
{
|
|
||||||
public function handle(Request $request, Closure $next)
|
|
||||||
{
|
|
||||||
$user = Auth::user();
|
|
||||||
if ($user->is_admin) {
|
|
||||||
return $next($request);
|
|
||||||
} else {
|
|
||||||
return response('Necesitás ser admin para hacer esto', 403);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,29 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Http\Middleware;
|
|
||||||
|
|
||||||
use Closure;
|
|
||||||
use Illuminate\Http\Request;
|
|
||||||
use Illuminate\Support\Facades\Auth;
|
|
||||||
|
|
||||||
class Compras
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Handle an incoming request.
|
|
||||||
*
|
|
||||||
* @param Request $request
|
|
||||||
* @param Closure $next
|
|
||||||
* @return mixed
|
|
||||||
*/
|
|
||||||
public function handle(Request $request, Closure $next)
|
|
||||||
{
|
|
||||||
if (!Auth::check())
|
|
||||||
return redirect()->route('compras_login.show');
|
|
||||||
|
|
||||||
if (Auth::user()->is_compras) {
|
|
||||||
return $next($request);
|
|
||||||
} else {
|
|
||||||
return response('Necesitás ser de comisión compras para hacer esto', 403);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -3,18 +3,17 @@
|
||||||
namespace App\Http\Middleware;
|
namespace App\Http\Middleware;
|
||||||
|
|
||||||
use Closure;
|
use Closure;
|
||||||
use Illuminate\Http\Request;
|
|
||||||
|
|
||||||
class Subpedido
|
class Subpedido
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Handle an incoming request.
|
* Handle an incoming request.
|
||||||
*
|
*
|
||||||
* @param Request $request
|
* @param \Illuminate\Http\Request $request
|
||||||
* @param Closure $next
|
* @param \Closure $next
|
||||||
* @return mixed
|
* @return mixed
|
||||||
*/
|
*/
|
||||||
public function handle(Request $request, Closure $next)
|
public function handle($request, Closure $next)
|
||||||
{
|
{
|
||||||
if (!session('subpedido_nombre') || !session('subpedido_id')) {
|
if (!session('subpedido_nombre') || !session('subpedido_id')) {
|
||||||
return redirect()->route('subpedidos.create');
|
return redirect()->route('subpedidos.create');
|
||||||
|
|
|
@ -1,31 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Http\Resources;
|
|
||||||
|
|
||||||
use Illuminate\Http\Request;
|
|
||||||
use Illuminate\Http\Resources\Json\JsonResource;
|
|
||||||
|
|
||||||
class GrupoDeCompraResource extends JsonResource
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Transform the resource into an array.
|
|
||||||
*
|
|
||||||
* @param Request $request
|
|
||||||
* @return array
|
|
||||||
*/
|
|
||||||
public function toArray($request): array
|
|
||||||
{
|
|
||||||
return [
|
|
||||||
'id' => $this->id,
|
|
||||||
'nombre' => $this->nombre,
|
|
||||||
'devoluciones_habilitadas' => $this->devoluciones_habilitadas,
|
|
||||||
'pedidos' => SubpedidoResource::collection($this->subpedidos),
|
|
||||||
'total_a_recaudar' => number_format($this->totalARecaudar(),2),
|
|
||||||
'total_barrial' => number_format($this->totalBarrial(),2),
|
|
||||||
'total_devoluciones' => number_format($this->totalDevoluciones(),2),
|
|
||||||
'total_a_transferir' => number_format($this->totalATransferir(),2),
|
|
||||||
'total_transporte' => number_format($this->totalTransporte()),
|
|
||||||
'cantidad_transporte' => number_format($this->cantidadTransporte()),
|
|
||||||
];
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -2,7 +2,6 @@
|
||||||
|
|
||||||
namespace App\Http\Resources;
|
namespace App\Http\Resources;
|
||||||
|
|
||||||
use Illuminate\Http\Request;
|
|
||||||
use Illuminate\Http\Resources\Json\JsonResource;
|
use Illuminate\Http\Resources\Json\JsonResource;
|
||||||
|
|
||||||
class ProductoResource extends JsonResource
|
class ProductoResource extends JsonResource
|
||||||
|
@ -10,10 +9,10 @@ class ProductoResource extends JsonResource
|
||||||
/**
|
/**
|
||||||
* Transform the resource into an array.
|
* Transform the resource into an array.
|
||||||
*
|
*
|
||||||
* @param Request $request
|
* @param \Illuminate\Http\Request $request
|
||||||
* @return array
|
* @return array
|
||||||
*/
|
*/
|
||||||
public function toArray($request): array
|
public function toArray($request)
|
||||||
{
|
{
|
||||||
return [
|
return [
|
||||||
'id' => $this->id,
|
'id' => $this->id,
|
||||||
|
@ -26,8 +25,7 @@ class ProductoResource extends JsonResource
|
||||||
'imagen' => optional($this->poster)->url(),
|
'imagen' => optional($this->poster)->url(),
|
||||||
'descripcion' => $this->descripcion,
|
'descripcion' => $this->descripcion,
|
||||||
'apto_veganxs' => $this->apto_veganxs,
|
'apto_veganxs' => $this->apto_veganxs,
|
||||||
'apto_celiacxs' => $this->apto_celiacxs,
|
'apto_celiacxs' => $this->apto_celiacxs
|
||||||
'requiere_notas' => $this->requiere_notas,
|
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,32 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Http\Resources;
|
|
||||||
|
|
||||||
use Illuminate\Http\Request;
|
|
||||||
use Illuminate\Http\Resources\Json\JsonResource;
|
|
||||||
|
|
||||||
class SubpedidoResource extends JsonResource
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Transform the resource into an array.
|
|
||||||
*
|
|
||||||
* @param Request $request
|
|
||||||
* @return array
|
|
||||||
*/
|
|
||||||
public function toArray($request): array
|
|
||||||
{
|
|
||||||
return [
|
|
||||||
'id' => $this->id,
|
|
||||||
'nombre' => $this->nombre,
|
|
||||||
'grupo_de_compra' => $this->grupoDeCompra,
|
|
||||||
'productos' => $this->productos,
|
|
||||||
'aprobado' => (bool) $this->aprobado,
|
|
||||||
'total' => number_format($this->total(),2),
|
|
||||||
'total_transporte' => number_format($this->totalTransporte()),
|
|
||||||
'cantidad_transporte' => number_format($this->cantidadTransporte()),
|
|
||||||
'total_sin_devoluciones' => number_format($this->totalSinDevoluciones(),2),
|
|
||||||
'devoluciones_total' => number_format($this->devoluciones_total,2),
|
|
||||||
'devoluciones_notas' => $this->devoluciones_notas
|
|
||||||
];
|
|
||||||
}
|
|
||||||
}
|
|
134
app/Producto.php
134
app/Producto.php
|
@ -2,153 +2,35 @@
|
||||||
|
|
||||||
namespace App;
|
namespace App;
|
||||||
|
|
||||||
use App\Filtros\FiltroDeProducto;
|
|
||||||
use App\Helpers\CsvHelper;
|
|
||||||
use App\Helpers\TransporteHelper;
|
|
||||||
use Illuminate\Database\Eloquent\Builder;
|
|
||||||
use Illuminate\Database\Eloquent\Model;
|
use Illuminate\Database\Eloquent\Model;
|
||||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
|
||||||
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
|
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
use Illuminate\Support\Collection;
|
use App\Filtros\FiltroDeProducto;
|
||||||
use Illuminate\Support\Facades\DB;
|
|
||||||
|
|
||||||
class Producto extends Model
|
class Producto extends Model
|
||||||
{
|
{
|
||||||
public $timestamps = false;
|
public $timestamps = false;
|
||||||
protected $fillable = ["nombre", "precio", "presentacion", "stock", "categoria"];
|
protected $fillable = [ "nombre", "precio", "presentacion", "stock", "categoria" ];
|
||||||
static int $paginarPorDefecto = 10;
|
static $paginarPorDefecto = 10;
|
||||||
|
|
||||||
public function subpedidos(): BelongsToMany
|
public function subpedidos()
|
||||||
{
|
{
|
||||||
return $this->belongsToMany('App\Subpedido', 'productos_subpedidos')->withPivot(["cantidad", "notas"]);
|
return $this->belongsToMany('App\Subpedido','productos_subpedidos')->withPivot(["cantidad"]);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function proveedor(): BelongsTo
|
public function proveedor()
|
||||||
{
|
{
|
||||||
return $this->belongsTo('App\Proveedor');
|
return $this->belongsTo('App\Proveedor');
|
||||||
}
|
}
|
||||||
|
|
||||||
//Este método permite que se apliquen los filtros al hacer una request (por ejemplo, de búsqueda)
|
//Este método permite que se apliquen los filtros al hacer una request (por ejemplo, de búsqueda)
|
||||||
public function scopeFiltrar($query, FiltroDeProducto $filtros): Builder
|
public function scopeFiltrar($query, FiltroDeProducto $filtros)
|
||||||
{
|
{
|
||||||
return $filtros->aplicar($query);
|
return $filtros->aplicar($query);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function getPaginar(Request $request): int
|
public static function getPaginar(Request $request)
|
||||||
{
|
{
|
||||||
return $request->has('paginar') && intval($request->input('paginar')) ? intval($request->input('paginar')) : self::$paginarPorDefecto;
|
return $request->has('paginar') && intval($request->input('paginar')) ? intval($request->input('paginar')) : self::$paginarPorDefecto;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function productosFilaID()
|
|
||||||
{
|
|
||||||
return Producto::pluck('id', 'fila')->all();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function productosIDFila()
|
|
||||||
{
|
|
||||||
return Producto::pluck('fila', 'id')->all();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function productosIDNombre()
|
|
||||||
{
|
|
||||||
return Producto::pluck('nombre', 'id')->all();
|
|
||||||
}
|
|
||||||
|
|
||||||
static public function cantidadesPorBarrio(): Collection
|
|
||||||
{
|
|
||||||
$barrios = GrupoDeCompra::barriosMenosPrueba()
|
|
||||||
->pluck('id', 'nombre');
|
|
||||||
|
|
||||||
$columnasBarrios = $barrios->map(function ($id, $nombre) {
|
|
||||||
return DB::raw("SUM(CASE WHEN subpedidos.grupo_de_compra_id = $id AND subpedidos.aprobado = 1 THEN producto_subpedido.cantidad ELSE 0 END) as `$nombre`");
|
|
||||||
})->toArray();
|
|
||||||
|
|
||||||
return DB::table('productos')
|
|
||||||
->where('productos.nombre', 'not like', '%barrial%')
|
|
||||||
->leftJoin('producto_subpedido', 'productos.id', '=', 'producto_subpedido.producto_id')
|
|
||||||
->leftJoin('subpedidos', 'subpedidos.id', '=', 'producto_subpedido.subpedido_id')
|
|
||||||
->select(array_merge(
|
|
||||||
['productos.fila as fila'],
|
|
||||||
['productos.nombre as producto'],
|
|
||||||
$columnasBarrios
|
|
||||||
))
|
|
||||||
->groupBy('productos.fila', 'productos.id', 'productos.nombre')
|
|
||||||
->orderBy('productos.fila')
|
|
||||||
->get();
|
|
||||||
}
|
|
||||||
|
|
||||||
static public function planillaTotales()
|
|
||||||
{
|
|
||||||
$headers = ['Producto'];
|
|
||||||
$barrios = GrupoDeCompra::barriosMenosPrueba()
|
|
||||||
->pluck('nombre')->toArray();
|
|
||||||
$headers = array_merge($headers, $barrios);
|
|
||||||
|
|
||||||
$cantidadesPorBarrio = self::cantidadesPorBarrio();
|
|
||||||
$transportePorBarrio = GrupoDeCompra::transportePorBarrio();
|
|
||||||
$planilla = [];
|
|
||||||
$ultimaFila = 1;
|
|
||||||
$filaTransporte = TransporteHelper::filaTransporte();
|
|
||||||
|
|
||||||
foreach ($cantidadesPorBarrio as $productoCantidades) {
|
|
||||||
$fila = $productoCantidades->fila;
|
|
||||||
while ($fila - $ultimaFila > 1) {
|
|
||||||
$ultimaFila++;
|
|
||||||
if ($ultimaFila == $filaTransporte) {
|
|
||||||
$planilla[$ultimaFila] = ['Bono de transporte'];
|
|
||||||
} else {
|
|
||||||
$planilla[$ultimaFila] = ['---'];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
$planilla[$fila] = [$productoCantidades->producto];
|
|
||||||
foreach ($barrios as $barrio) {
|
|
||||||
$planilla[$fila][] = $productoCantidades->$barrio ?? 0;
|
|
||||||
}
|
|
||||||
$ultimaFila = $fila;
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach ($transportePorBarrio as $key => $cantidad) {
|
|
||||||
$planilla[$filaTransporte][] = $cantidad;
|
|
||||||
}
|
|
||||||
|
|
||||||
CsvHelper::generarCsv('csv/exports/pedidos-por-barrio.csv', $planilla, $headers);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function notasPorBarrio(): Collection
|
|
||||||
{
|
|
||||||
return DB::table('productos')
|
|
||||||
->join('producto_subpedido', 'productos.id', '=', 'producto_subpedido.producto_id')
|
|
||||||
->join('subpedidos', 'producto_subpedido.subpedido_id', '=', 'subpedidos.id')
|
|
||||||
->join('grupos_de_compra', 'subpedidos.grupo_de_compra_id', '=', 'grupos_de_compra.id')
|
|
||||||
->where('productos.requiere_notas', 1)
|
|
||||||
->select(
|
|
||||||
'productos.nombre as producto',
|
|
||||||
'grupos_de_compra.nombre as barrio',
|
|
||||||
'producto_subpedido.notas'
|
|
||||||
)
|
|
||||||
->get()
|
|
||||||
->groupBy('producto');
|
|
||||||
}
|
|
||||||
|
|
||||||
static public function planillaNotas() {
|
|
||||||
$headers = ['Producto'];
|
|
||||||
$barrios = GrupoDeCompra::barriosMenosPrueba()
|
|
||||||
->pluck('nombre')->toArray();
|
|
||||||
$headers = array_merge($headers, $barrios);
|
|
||||||
|
|
||||||
$notasPorBarrio = self::notasPorBarrio();
|
|
||||||
$planilla = [];
|
|
||||||
|
|
||||||
foreach ($notasPorBarrio as $producto => $notasGrupo) {
|
|
||||||
$fila = [$producto];
|
|
||||||
foreach ($barrios as $barrio) {
|
|
||||||
$notas = $notasGrupo->where('barrio', $barrio)->pluck('notas')->implode('; ');
|
|
||||||
$fila[] = $notas ?: '';
|
|
||||||
}
|
|
||||||
$planilla[] = $fila;
|
|
||||||
}
|
|
||||||
|
|
||||||
CsvHelper::generarCsv('csv/exports/notas-por-barrio.csv', $planilla, $headers);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,6 @@
|
||||||
namespace App;
|
namespace App;
|
||||||
|
|
||||||
use Illuminate\Database\Eloquent\Model;
|
use Illuminate\Database\Eloquent\Model;
|
||||||
use Illuminate\Database\Eloquent\Relations\HasMany;
|
|
||||||
|
|
||||||
class Proveedor extends Model
|
class Proveedor extends Model
|
||||||
{
|
{
|
||||||
|
@ -11,7 +10,7 @@ class Proveedor extends Model
|
||||||
protected $fillable = [ "nombre","direccion","telefono","correo","comentario" ];
|
protected $fillable = [ "nombre","direccion","telefono","correo","comentario" ];
|
||||||
protected $table = 'proveedores';
|
protected $table = 'proveedores';
|
||||||
|
|
||||||
public function productos(): HasMany
|
public function productos()
|
||||||
{
|
{
|
||||||
return $this->hasMany('App\Producto');
|
return $this->hasMany('App\Producto');
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,130 +2,31 @@
|
||||||
|
|
||||||
namespace App;
|
namespace App;
|
||||||
|
|
||||||
use App\Helpers\TransporteHelper;
|
use League\Csv\Reader;
|
||||||
use Illuminate\Database\Eloquent\Builder;
|
|
||||||
use Illuminate\Database\Eloquent\Model;
|
use Illuminate\Database\Eloquent\Model;
|
||||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
|
||||||
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
|
|
||||||
use Illuminate\Support\Facades\DB;
|
use Illuminate\Support\Facades\DB;
|
||||||
|
use Log;
|
||||||
use App\Filtros\FiltroDeSubpedido;
|
use App\Filtros\FiltroDeSubpedido;
|
||||||
|
|
||||||
class Subpedido extends Model
|
class Subpedido extends Model
|
||||||
{
|
{
|
||||||
public $timestamps = false;
|
public $timestamps = false;
|
||||||
protected $fillable = ['grupo_de_compra_id', 'aprobado', 'nombre', 'devoluciones_total', 'devoluciones_notas'];
|
protected $fillable = ['grupo_de_compra_id', 'aprobado', 'nombre'];
|
||||||
|
|
||||||
public function productos(): BelongsToMany
|
public function productos()
|
||||||
{
|
{
|
||||||
return $this->belongsToMany('App\Producto')->withPivot(["cantidad", "total", "notas"]);
|
return $this->belongsToMany('App\Producto')->withPivot(["cantidad"]);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function grupoDeCompra(): BelongsTo
|
public function grupoDeCompra()
|
||||||
{
|
{
|
||||||
return $this->belongsTo('App\GrupoDeCompra');
|
return $this->belongsTo('App\GrupoDeCompra');
|
||||||
}
|
}
|
||||||
|
|
||||||
// Permite que se apliquen los filtros al hacer una request (por ejemplo, de búsqueda)
|
//Este método permite que se apliquen los filtros al hacer una request (por ejemplo, de búsqueda)
|
||||||
public function scopeFiltrar($query, FiltroDeSubpedido $filtros): Builder
|
public function scopeFiltrar($query, FiltroDeSubpedido $filtros)
|
||||||
{
|
{
|
||||||
return $filtros->aplicar($query);
|
return $filtros->aplicar($query);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function total()
|
|
||||||
{
|
|
||||||
return $this->totalSinDevoluciones() - $this->devoluciones_total;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function totalSinDevoluciones()
|
|
||||||
{
|
|
||||||
return $this->totalBarrial() + $this->totalCentral();
|
|
||||||
}
|
|
||||||
|
|
||||||
public function totalBarrial()
|
|
||||||
{
|
|
||||||
return DB::table('producto_subpedido')
|
|
||||||
->join('productos', 'producto_subpedido.producto_id', '=', 'productos.id')
|
|
||||||
->where('producto_subpedido.subpedido_id', $this->id)
|
|
||||||
->where('productos.nombre', 'like', '%barrial%')
|
|
||||||
->selectRaw('SUM(productos.precio * producto_subpedido.cantidad) as total')
|
|
||||||
->value('total');
|
|
||||||
}
|
|
||||||
|
|
||||||
public function totalCentral()
|
|
||||||
{
|
|
||||||
return $this->totalCentralesQueNoPaganTransporte() + $this->totalCentralesQuePaganTransporte() + $this->totalTransporte();
|
|
||||||
}
|
|
||||||
|
|
||||||
public function totalCentralesQueNoPaganTransporte()
|
|
||||||
{
|
|
||||||
return DB::table('producto_subpedido')
|
|
||||||
->join('productos', 'producto_subpedido.producto_id', '=', 'productos.id')
|
|
||||||
->where('producto_subpedido.subpedido_id', $this->id)
|
|
||||||
->where('productos.nombre', 'not like', '%barrial%')
|
|
||||||
->where(function ($query) {
|
|
||||||
$query->where('productos.categoria', 'like', '%SUBSIDIADO%')
|
|
||||||
->orWhere('productos.bono', true);
|
|
||||||
})
|
|
||||||
->selectRaw('SUM(productos.precio * producto_subpedido.cantidad) as total')
|
|
||||||
->value('total');
|
|
||||||
}
|
|
||||||
|
|
||||||
public function totalCentralesQuePaganTransporte()
|
|
||||||
{
|
|
||||||
return DB::table('producto_subpedido')
|
|
||||||
->join('productos', 'producto_subpedido.producto_id', '=', 'productos.id')
|
|
||||||
->where('producto_subpedido.subpedido_id', $this->id)
|
|
||||||
->where('productos.nombre', 'not like', '%barrial%')
|
|
||||||
->where('productos.bono', false)
|
|
||||||
->where('productos.categoria', 'not like', '%SUBSIDIADO%')
|
|
||||||
->selectRaw('SUM(productos.precio * producto_subpedido.cantidad) as total')
|
|
||||||
->value('total');
|
|
||||||
}
|
|
||||||
|
|
||||||
public function totalTransporte()
|
|
||||||
{
|
|
||||||
return TransporteHelper::totalTransporte($this->totalCentralesQuePaganTransporte());
|
|
||||||
}
|
|
||||||
|
|
||||||
public function cantidadTransporte()
|
|
||||||
{
|
|
||||||
return TransporteHelper::cantidadTransporte($this->totalCentralesQuePaganTransporte());
|
|
||||||
}
|
|
||||||
|
|
||||||
//Actualiza el pedido, agregando o quitando del subpedido según sea necesario. Debe ser llamado desde el controlador de subpedidos, luego de validar que los parámetros $producto y $cantidad son correctos. También calcula el subtotal por producto.
|
|
||||||
public function syncProducto(Producto $producto, int $cantidad, string $notas)
|
|
||||||
{
|
|
||||||
if ($cantidad) {
|
|
||||||
//si la cantidad es 1 o más se agrega el producto o actualiza la cantidad
|
|
||||||
$this->productos()->syncWithoutDetaching([
|
|
||||||
$producto->id => [
|
|
||||||
'cantidad' => $cantidad,
|
|
||||||
'total' => $cantidad * $producto->precio,
|
|
||||||
'notas' => $notas,
|
|
||||||
]
|
|
||||||
]);
|
|
||||||
} else {
|
|
||||||
//si la cantidad es 0, se elimina el producto del subpedido
|
|
||||||
$this->productos()->detach($producto->id);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public function toggleAprobacion(bool $aprobacion)
|
|
||||||
{
|
|
||||||
$this->aprobado = $aprobacion;
|
|
||||||
$this->save();
|
|
||||||
}
|
|
||||||
|
|
||||||
public function generarHTML()
|
|
||||||
{
|
|
||||||
$view = view("pdfgen.pedido_tabla", ["pedido" => $this]);
|
|
||||||
return $view->render();
|
|
||||||
}
|
|
||||||
|
|
||||||
public function syncDevoluciones(float $total, string $notas)
|
|
||||||
{
|
|
||||||
$this->devoluciones_total = $total;
|
|
||||||
$this->devoluciones_notas = $notas;
|
|
||||||
$this->save();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
namespace App;
|
namespace App;
|
||||||
|
|
||||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
use Illuminate\Contracts\Auth\MustVerifyEmail;
|
||||||
use Illuminate\Foundation\Auth\User as Authenticatable;
|
use Illuminate\Foundation\Auth\User as Authenticatable;
|
||||||
use Illuminate\Notifications\Notifiable;
|
use Illuminate\Notifications\Notifiable;
|
||||||
|
|
||||||
|
@ -38,7 +38,7 @@ class User extends Authenticatable
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|
||||||
public function grupoDeCompra(): BelongsTo
|
public function grupoDeCompra()
|
||||||
{
|
{
|
||||||
return $this->belongsTo('App\GrupoDeCompra');
|
return $this->belongsTo('App\GrupoDeCompra');
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
],
|
],
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"require": {
|
"require": {
|
||||||
"php": "^7.4",
|
"php": "^7.2.5|^8.0",
|
||||||
"fideloper/proxy": "^4.4",
|
"fideloper/proxy": "^4.4",
|
||||||
"fruitcake/laravel-cors": "^2.0",
|
"fruitcake/laravel-cors": "^2.0",
|
||||||
"guzzlehttp/guzzle": "^6.3.1|^7.0.1",
|
"guzzlehttp/guzzle": "^6.3.1|^7.0.1",
|
||||||
|
@ -16,9 +16,7 @@
|
||||||
"laravel/sanctum": "^2.13",
|
"laravel/sanctum": "^2.13",
|
||||||
"laravel/tinker": "^2.5",
|
"laravel/tinker": "^2.5",
|
||||||
"laravel/ui": "*",
|
"laravel/ui": "*",
|
||||||
"league/csv": "^9.8",
|
"league/csv": "^9.8"
|
||||||
"mpdf/mpdf": "^8.1",
|
|
||||||
"prexview/prexview": "^1.1"
|
|
||||||
},
|
},
|
||||||
"require-dev": {
|
"require-dev": {
|
||||||
"facade/ignition": "^2.0",
|
"facade/ignition": "^2.0",
|
||||||
|
@ -54,13 +52,13 @@
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"post-autoload-dump": [
|
"post-autoload-dump": [
|
||||||
"Illuminate\\Foundation\\ComposerScripts::postAutoloadDump",
|
"Illuminate\\Foundation\\ComposerScripts::postAutoloadDump",
|
||||||
"@php7.4 artisan package:discover --ansi"
|
"@php artisan package:discover --ansi"
|
||||||
],
|
],
|
||||||
"post-root-package-install": [
|
"post-root-package-install": [
|
||||||
"@php7.4 -r \"file_exists('.env') || copy('.env.example', '.env');\""
|
"@php -r \"file_exists('.env') || copy('.env.example', '.env');\""
|
||||||
],
|
],
|
||||||
"post-create-project-cmd": [
|
"post-create-project-cmd": [
|
||||||
"@php7.4 artisan key:generate --ansi"
|
"@php artisan key:generate --ansi"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
1846
composer.lock
generated
1846
composer.lock
generated
File diff suppressed because it is too large
Load diff
|
@ -1,10 +1,9 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
/** @var Factory $factory */
|
/** @var \Illuminate\Database\Eloquent\Factory $factory */
|
||||||
|
|
||||||
use App\User;
|
use App\User;
|
||||||
use Faker\Generator as Faker;
|
use Faker\Generator as Faker;
|
||||||
use Illuminate\Database\Eloquent\Factory;
|
|
||||||
use Illuminate\Support\Str;
|
use Illuminate\Support\Str;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -19,8 +19,6 @@ class CreateUsersTable extends Migration
|
||||||
$table->string('email')->unique()->nullable();
|
$table->string('email')->unique()->nullable();
|
||||||
$table->timestamp('email_verified_at')->nullable();
|
$table->timestamp('email_verified_at')->nullable();
|
||||||
$table->foreignId('grupo_de_compra_id')->nullable();
|
$table->foreignId('grupo_de_compra_id')->nullable();
|
||||||
$table->boolean('is_admin');
|
|
||||||
$table->unique(['name', 'is_admin']);
|
|
||||||
$table->string('password');
|
$table->string('password');
|
||||||
$table->rememberToken();
|
$table->rememberToken();
|
||||||
$table->timestamps();
|
$table->timestamps();
|
||||||
|
|
|
@ -17,7 +17,7 @@ class CreateSubpedidosTable extends Migration
|
||||||
$table->id();
|
$table->id();
|
||||||
$table->string('nombre');
|
$table->string('nombre');
|
||||||
$table->foreignId('grupo_de_compra_id');
|
$table->foreignId('grupo_de_compra_id');
|
||||||
$table->boolean('aprobado')->default(false);
|
$table->boolean('aprobado')->nullable();
|
||||||
$table->timestamps();
|
$table->timestamps();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -1,32 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
use Illuminate\Database\Migrations\Migration;
|
|
||||||
use Illuminate\Database\Schema\Blueprint;
|
|
||||||
use Illuminate\Support\Facades\Schema;
|
|
||||||
|
|
||||||
class AgregarColumnaBonoATablaDeProductos extends Migration
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Run the migrations.
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
public function up()
|
|
||||||
{
|
|
||||||
Schema::table('productos', function (Blueprint $table) {
|
|
||||||
$table->boolean('bono')->after('apto_celiacxs');
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Reverse the migrations.
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
public function down()
|
|
||||||
{
|
|
||||||
Schema::table('productos', function (Blueprint $table) {
|
|
||||||
$table->dropColumn('bono');
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,32 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
use Illuminate\Database\Migrations\Migration;
|
|
||||||
use Illuminate\Database\Schema\Blueprint;
|
|
||||||
use Illuminate\Support\Facades\Schema;
|
|
||||||
|
|
||||||
class AgregarColumnaTotalATablaDeProductoSubpedido extends Migration
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Run the migrations.
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
public function up()
|
|
||||||
{
|
|
||||||
Schema::table('producto_subpedido', function (Blueprint $table) {
|
|
||||||
$table->double('total',10,2)->after('cantidad')->default(0);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Reverse the migrations.
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
public function down()
|
|
||||||
{
|
|
||||||
Schema::table('producto_subpedido', function (Blueprint $table) {
|
|
||||||
$table->dropColumn('total');
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,32 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
use Illuminate\Database\Migrations\Migration;
|
|
||||||
use Illuminate\Database\Schema\Blueprint;
|
|
||||||
use Illuminate\Support\Facades\Schema;
|
|
||||||
|
|
||||||
class AgregarColumnaFilaEnPlanillaATablaDeProductos extends Migration
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Run the migrations.
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
public function up()
|
|
||||||
{
|
|
||||||
Schema::table('productos', function (Blueprint $table) {
|
|
||||||
$table->integer('fila')->after('id');
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Reverse the migrations.
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
public function down()
|
|
||||||
{
|
|
||||||
Schema::table('productos', function (Blueprint $table) {
|
|
||||||
$table->dropColumn('fila');
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,26 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
use Illuminate\Database\Migrations\Migration;
|
|
||||||
|
|
||||||
class CallCrearPedidosAprobados extends Migration
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Run the migrations.
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
public function up()
|
|
||||||
{
|
|
||||||
Artisan::call("view:CrearPedidosAprobadosView");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Reverse the migrations.
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
public function down()
|
|
||||||
{
|
|
||||||
//
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,34 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
use Illuminate\Database\Migrations\Migration;
|
|
||||||
use Illuminate\Database\Schema\Blueprint;
|
|
||||||
use Illuminate\Support\Facades\Schema;
|
|
||||||
|
|
||||||
class DevolucionesPedido extends Migration
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Run the migrations.
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
public function up()
|
|
||||||
{
|
|
||||||
Schema::table('subpedidos', function (Blueprint $table) {
|
|
||||||
$table->double('devoluciones_total', 10, 2)->default(0);
|
|
||||||
$table->string('devoluciones_notas')->default("");
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Reverse the migrations.
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
public function down()
|
|
||||||
{
|
|
||||||
Schema::table('subpedidos', function (Blueprint $table) {
|
|
||||||
$table->dropColumn('devoluciones_total');
|
|
||||||
$table->dropColumn('devoluciones_notas');
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,32 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
use Illuminate\Database\Migrations\Migration;
|
|
||||||
use Illuminate\Database\Schema\Blueprint;
|
|
||||||
use Illuminate\Support\Facades\Schema;
|
|
||||||
|
|
||||||
class HabilitarDevoluciones extends Migration
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Run the migrations.
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
public function up()
|
|
||||||
{
|
|
||||||
Schema::table('grupos_de_compra', function (Blueprint $table) {
|
|
||||||
$table->boolean('devoluciones_habilitadas')->default(false);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Reverse the migrations.
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
public function down()
|
|
||||||
{
|
|
||||||
Schema::table('grupos_de_compra', function (Blueprint $table) {
|
|
||||||
$table->dropColumn('devoluciones_habilitadas');
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,32 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
use Illuminate\Database\Migrations\Migration;
|
|
||||||
use Illuminate\Database\Schema\Blueprint;
|
|
||||||
use Illuminate\Support\Facades\Schema;
|
|
||||||
|
|
||||||
class AgregarIsComprasAUser extends Migration
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Run the migrations.
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
public function up()
|
|
||||||
{
|
|
||||||
Schema::table('users', function (Blueprint $table) {
|
|
||||||
$table->boolean('is_compras')->after('is_admin')->default(0);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Reverse the migrations.
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
public function down()
|
|
||||||
{
|
|
||||||
Schema::table('users', function (Blueprint $table) {
|
|
||||||
$table->dropColumn('is_compras');
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,32 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
use Illuminate\Database\Migrations\Migration;
|
|
||||||
use Illuminate\Database\Schema\Blueprint;
|
|
||||||
use Illuminate\Support\Facades\Schema;
|
|
||||||
|
|
||||||
class NotasProducto extends Migration
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Run the migrations.
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
public function up()
|
|
||||||
{
|
|
||||||
Schema::table('producto_subpedido', function (Blueprint $table) {
|
|
||||||
$table->string('notas')->nullable();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Reverse the migrations.
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
public function down()
|
|
||||||
{
|
|
||||||
Schema::table('producto_subpedido', function (Blueprint $table) {
|
|
||||||
$table->dropColumn('notas');
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,32 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
use Illuminate\Database\Migrations\Migration;
|
|
||||||
use Illuminate\Database\Schema\Blueprint;
|
|
||||||
use Illuminate\Support\Facades\Schema;
|
|
||||||
|
|
||||||
class ProductoRequiereNotas extends Migration
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Run the migrations.
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
public function up()
|
|
||||||
{
|
|
||||||
Schema::table('productos', function (Blueprint $table) {
|
|
||||||
$table->boolean('requiere_notas')->default(false);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Reverse the migrations.
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
public function down()
|
|
||||||
{
|
|
||||||
Schema::table('productos', function (Blueprint $table) {
|
|
||||||
$table->dropColumn('requiere_notas');
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,33 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
use Illuminate\Database\Migrations\Migration;
|
|
||||||
use Illuminate\Database\Schema\Blueprint;
|
|
||||||
use Illuminate\Support\Facades\Schema;
|
|
||||||
|
|
||||||
class CrearCargaDeCanastas extends Migration
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Run the migrations.
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
public function up()
|
|
||||||
{
|
|
||||||
Schema::create('carga_de_canastas', function (Blueprint $table) {
|
|
||||||
$table->id();
|
|
||||||
$table->string('path');
|
|
||||||
$table->string('descripcion');
|
|
||||||
$table->timestamps();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Reverse the migrations.
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
public function down()
|
|
||||||
{
|
|
||||||
Schema::dropIfExists('carga_de_canastas');
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,27 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
use Illuminate\Database\Migrations\Migration;
|
|
||||||
use Illuminate\Support\Facades\Artisan;
|
|
||||||
|
|
||||||
class CallAgregarEsBonoAPedidosAprobados extends Migration
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Run the migrations.
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
public function up()
|
|
||||||
{
|
|
||||||
Artisan::call("command:AgregarEsBonoAPedidosAprobados");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Reverse the migrations.
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
public function down()
|
|
||||||
{
|
|
||||||
//
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,19 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
use App\Helpers\CanastaHelper;
|
|
||||||
use Illuminate\Database\Seeder;
|
|
||||||
|
|
||||||
class CanastaSeeder extends Seeder
|
|
||||||
{
|
|
||||||
const ARCHIVO_DEFAULT = 'csv/productos.csv';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Run the database seeds.
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
public function run()
|
|
||||||
{
|
|
||||||
CanastaHelper::cargarCanasta(self::ARCHIVO_DEFAULT);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -12,8 +12,7 @@ class DatabaseSeeder extends Seeder
|
||||||
*/
|
*/
|
||||||
public function run()
|
public function run()
|
||||||
{
|
{
|
||||||
$this->call(CanastaSeeder::class);
|
|
||||||
$this->call(GrupoDeCompraSeeder::class);
|
$this->call(GrupoDeCompraSeeder::class);
|
||||||
$this->call(UserSeeder::class);
|
$this->call(ProductoSeeder::class);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +1,7 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
use App\Helpers\CsvHelper as CsvHelperAlias;
|
|
||||||
use Illuminate\Database\Seeder;
|
use Illuminate\Database\Seeder;
|
||||||
use Illuminate\Support\Facades\DB;
|
use League\Csv\Reader;
|
||||||
use Illuminate\Support\Facades\Hash;
|
|
||||||
|
|
||||||
class GrupoDeCompraSeeder extends Seeder
|
class GrupoDeCompraSeeder extends Seeder
|
||||||
{
|
{
|
||||||
|
@ -14,7 +12,11 @@ class GrupoDeCompraSeeder extends Seeder
|
||||||
*/
|
*/
|
||||||
public function run()
|
public function run()
|
||||||
{
|
{
|
||||||
$registros = CsvHelperAlias::getRecords('csv/barrios.csv');
|
$csv = Reader::createFromPath(resource_path('csv/barrios.csv'), 'r');
|
||||||
|
$csv->setDelimiter("|");
|
||||||
|
$csv->setEnclosure("'");
|
||||||
|
$csv->setHeaderOffset(0);
|
||||||
|
$registros = $csv->getRecords();
|
||||||
$gdcToInsert = [];
|
$gdcToInsert = [];
|
||||||
$usersToInsert = [];
|
$usersToInsert = [];
|
||||||
|
|
||||||
|
@ -29,15 +31,7 @@ class GrupoDeCompraSeeder extends Seeder
|
||||||
|
|
||||||
$usersToInsert[] = [
|
$usersToInsert[] = [
|
||||||
'name' => $registro['barrio'],
|
'name' => $registro['barrio'],
|
||||||
'password' => Hash::make("123"),
|
'password' => Hash::make($registro['barrio']),
|
||||||
"is_admin" => 0,
|
|
||||||
'grupo_de_compra_id' => $key
|
|
||||||
];
|
|
||||||
|
|
||||||
$usersToInsert[] = [
|
|
||||||
'name' => $registro['barrio'] . "_admin",
|
|
||||||
'password' => Hash::make("123"),
|
|
||||||
"is_admin" => 1,
|
|
||||||
'grupo_de_compra_id' => $key
|
'grupo_de_compra_id' => $key
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
39
database/seeds/ProductoSeeder.php
Normal file
39
database/seeds/ProductoSeeder.php
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Database\Seeder;
|
||||||
|
use League\Csv\Reader;
|
||||||
|
use App\Proveedor;
|
||||||
|
|
||||||
|
class ProductoSeeder extends Seeder
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Run the database seeds.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function run()
|
||||||
|
{
|
||||||
|
$csv = Reader::createFromPath(resource_path('csv/productos.csv'), 'r');
|
||||||
|
$csv->setDelimiter("|");
|
||||||
|
$csv->setEnclosure("'");
|
||||||
|
$csv->setHeaderOffset(0);
|
||||||
|
$registros = $csv->getRecords();
|
||||||
|
$toInsert = [];
|
||||||
|
|
||||||
|
foreach($registros as $registro){
|
||||||
|
$toInsert[] = [
|
||||||
|
'categoria' => $registro['categoria'],
|
||||||
|
'nombre' => $registro['producto'],
|
||||||
|
'precio' => $registro['precio'],
|
||||||
|
'proveedor_id' => isset($registro['proveedor']) ? Proveedor::firstOrCreate([
|
||||||
|
'nombre' => $registro['proveedor']
|
||||||
|
])->id : null
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (array_chunk($toInsert,DatabaseSeeder::CHUNK_SIZE) as $chunk)
|
||||||
|
{
|
||||||
|
DB::table('productos')->insert($chunk);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,31 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
use Illuminate\Database\Seeder;
|
|
||||||
use Illuminate\Support\Facades\DB;
|
|
||||||
use Illuminate\Support\Facades\Hash;
|
|
||||||
|
|
||||||
class UserSeeder extends Seeder
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Run the database seeds.
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
public function run()
|
|
||||||
{
|
|
||||||
$usersToInsert = [];
|
|
||||||
|
|
||||||
$usersToInsert[] = [
|
|
||||||
'name' => 'compras',
|
|
||||||
'password' => Hash::make("123"),
|
|
||||||
'is_admin' => 0,
|
|
||||||
'is_compras' => 1
|
|
||||||
];
|
|
||||||
|
|
||||||
|
|
||||||
foreach (array_chunk($usersToInsert,DatabaseSeeder::CHUNK_SIZE) as $chunk)
|
|
||||||
{
|
|
||||||
DB::table('users')->insert($chunk);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,2 +0,0 @@
|
||||||
#!/usr/bin/bash
|
|
||||||
docker-compose up -d && docker-compose exec app npm run watch
|
|
|
@ -1,15 +1,14 @@
|
||||||
version: '3.2'
|
version: "3.7"
|
||||||
|
|
||||||
services:
|
services:
|
||||||
app:
|
app:
|
||||||
build:
|
build:
|
||||||
args:
|
args:
|
||||||
user: www
|
user: www
|
||||||
uid: ${USERID}
|
uid: 1000
|
||||||
context: ./
|
context: ./
|
||||||
dockerfile: Dockerfile
|
dockerfile: Dockerfile
|
||||||
image: laravel-image
|
image: laravel-image
|
||||||
container_name: pedi2-app
|
container_name: laravel-app
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
working_dir: /var/www/
|
working_dir: /var/www/
|
||||||
volumes:
|
volumes:
|
||||||
|
@ -20,8 +19,10 @@ services:
|
||||||
|
|
||||||
db:
|
db:
|
||||||
image: mysql:5.7
|
image: mysql:5.7
|
||||||
container_name: pedi2-db
|
container_name: laravel-db
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
|
ports:
|
||||||
|
- "3306:3306"
|
||||||
environment:
|
environment:
|
||||||
MYSQL_DATABASE: ${DB_DATABASE}
|
MYSQL_DATABASE: ${DB_DATABASE}
|
||||||
MYSQL_ROOT_PASSWORD: ${DB_PASSWORD}
|
MYSQL_ROOT_PASSWORD: ${DB_PASSWORD}
|
||||||
|
@ -35,15 +36,13 @@ services:
|
||||||
- dbdata:/var/lib/mysql
|
- dbdata:/var/lib/mysql
|
||||||
networks:
|
networks:
|
||||||
- app-network
|
- app-network
|
||||||
ports:
|
|
||||||
- ${DB_PORT_EXPOSED}:3306
|
|
||||||
|
|
||||||
nginx:
|
nginx:
|
||||||
image: nginx:alpine
|
image: nginx:alpine
|
||||||
container_name: pedi2-nginx
|
container_name: laravel-nginx
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
ports:
|
ports:
|
||||||
- ${NGINX_PORT}:80
|
- 8000:80
|
||||||
volumes:
|
volumes:
|
||||||
- ./:/var/www
|
- ./:/var/www
|
||||||
- ./nginx/conf.d/:/etc/nginx/conf.d/
|
- ./nginx/conf.d/:/etc/nginx/conf.d/
|
||||||
|
|
26581
package-lock.json
generated
26581
package-lock.json
generated
File diff suppressed because it is too large
Load diff
10
package.json
10
package.json
|
@ -10,9 +10,9 @@
|
||||||
"production": "cross-env NODE_ENV=production node_modules/webpack/bin/webpack.js --no-progress --config=node_modules/laravel-mix/setup/webpack.config.js"
|
"production": "cross-env NODE_ENV=production node_modules/webpack/bin/webpack.js --no-progress --config=node_modules/laravel-mix/setup/webpack.config.js"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"axios": "^0.19.2",
|
"axios": "^0.19",
|
||||||
"bootstrap": "^4.0.0",
|
"bootstrap": "^4.0.0",
|
||||||
"cross-env": "^7.0.3",
|
"cross-env": "^7.0",
|
||||||
"jquery": "^3.2",
|
"jquery": "^3.2",
|
||||||
"laravel-mix": "^5.0.1",
|
"laravel-mix": "^5.0.1",
|
||||||
"lodash": "^4.17.19",
|
"lodash": "^4.17.19",
|
||||||
|
@ -22,11 +22,5 @@
|
||||||
"sass-loader": "^8.0.0",
|
"sass-loader": "^8.0.0",
|
||||||
"vue": "^2.5.17",
|
"vue": "^2.5.17",
|
||||||
"vue-template-compiler": "^2.6.10"
|
"vue-template-compiler": "^2.6.10"
|
||||||
},
|
|
||||||
"dependencies": {
|
|
||||||
"animate.css": "^4.1.1",
|
|
||||||
"bulma": "^0.9.4",
|
|
||||||
"bulma-switch": "^2.0.4",
|
|
||||||
"bulma-toast": "^2.4.1"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 2.4 KiB |
Binary file not shown.
Before Width: | Height: | Size: 3.1 KiB |
8
public/css/app.css
vendored
Normal file
8
public/css/app.css
vendored
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
p.navbar-item:empty {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.breadcrumb a {
|
||||||
|
color: #cc0f35;
|
||||||
|
}
|
||||||
|
|
4
public/css/productos.css
vendored
Normal file
4
public/css/productos.css
vendored
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
figure.image.icono {
|
||||||
|
float: right;
|
||||||
|
margin: 4px;
|
||||||
|
}
|
73
public/js/app.js
vendored
Normal file
73
public/js/app.js
vendored
Normal file
|
@ -0,0 +1,73 @@
|
||||||
|
window.Event = new Vue();
|
||||||
|
|
||||||
|
Vue.component('nav-bar', {
|
||||||
|
template: `
|
||||||
|
<nav class="navbar is-danger" role="navigation" aria-label="main navigation">
|
||||||
|
<div class="navbar-brand">
|
||||||
|
<a class="navbar-item" href="https://mps.org.uy">
|
||||||
|
<img src="/assets/logoMPS.png" height="28">
|
||||||
|
</a>
|
||||||
|
<p style="margin:0 auto" class="navbar-item"><slot name="subpedido"></slot></p>
|
||||||
|
<a role="button" class="navbar-burger" :class="{'is-active':isActive}" aria-label="menu" aria-expanded="false" data-target="navbarBasicExample" @click="toggleState">
|
||||||
|
<span aria-hidden="true"></span>
|
||||||
|
<span aria-hidden="true"></span>
|
||||||
|
<span aria-hidden="true"></span>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="navbarBasicExample" class="navbar-menu" :class="{'is-active':isActive}">
|
||||||
|
<div class="navbar-start has-text-right-mobile">
|
||||||
|
<!-- Styles nombre del barrio-->
|
||||||
|
<p class="navbar-item"><slot name="gdc"></slot></p>
|
||||||
|
<a class="navbar-item"
|
||||||
|
onclick="event.preventDefault();
|
||||||
|
document.getElementById('logout-form').submit();">
|
||||||
|
Cerrar sesión
|
||||||
|
</a>
|
||||||
|
<slot name="logout-form"></slot>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</nav>`,
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
isActive: false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
toggleState() {
|
||||||
|
this.isActive = !this.isActive;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
Vue.component('nav-migas', {
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
migas: []
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
visible: function() {
|
||||||
|
return this.migas.length > 0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
Event.$on('migas-setear-como-inicio', (miga) => {
|
||||||
|
this.migas = [];
|
||||||
|
this.migas.push(miga);
|
||||||
|
});
|
||||||
|
Event.$on('migas-agregar', (miga) => {
|
||||||
|
this.migas.push(miga);
|
||||||
|
});
|
||||||
|
Event.$on('migas-reset', () => {
|
||||||
|
this.migas = [];
|
||||||
|
});
|
||||||
|
Event.$on('migas-pop', () => {
|
||||||
|
this.migas.pop();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
new Vue({
|
||||||
|
el: '#app'
|
||||||
|
});
|
114
public/js/login.js
vendored
Normal file
114
public/js/login.js
vendored
Normal file
|
@ -0,0 +1,114 @@
|
||||||
|
window.Event = new Vue();
|
||||||
|
|
||||||
|
Vue.component('region-select', {
|
||||||
|
template: `
|
||||||
|
<div class="block">
|
||||||
|
<div class="field">
|
||||||
|
<label class="label">Seleccioná tu región</label>
|
||||||
|
<div class="control">
|
||||||
|
<div class="select">
|
||||||
|
<select @change="onRegionSelected" v-model="region">
|
||||||
|
<option :disabled="isDefaultDisabled==1" value=null>Seleccionar</option>
|
||||||
|
<option v-for="region in regiones" v-text="region" :name="region"></option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>`,
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
regiones: [],
|
||||||
|
isDefaultDisabled: 0,
|
||||||
|
region: null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
axios.get("/api/regiones").then(response => this.regiones = response.data);
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
onRegionSelected() {
|
||||||
|
this.isDefaultDisabled = 1;
|
||||||
|
Event.$emit("region-seleccionada",this.region);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
Vue.component('barrio-select', {
|
||||||
|
template: `
|
||||||
|
<div v-show="visible" class="block">
|
||||||
|
<div class="field">
|
||||||
|
<label class="label">Seleccioná tu barrio o grupo de compra</label>
|
||||||
|
<div class="control">
|
||||||
|
<div class="select">
|
||||||
|
<select @change="onGDCSelected" v-model="gdc" name="name">
|
||||||
|
<option :disabled="isDefaultDisabled==1" value=null>Seleccionar</option>
|
||||||
|
<option v-for="gdc in gdcs" v-text="gdc.nombre" :name="gdc.nombre"></option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>`,
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
visible: false,
|
||||||
|
region: null,
|
||||||
|
gdcs: [],
|
||||||
|
isDefaultDisabled: 0,
|
||||||
|
gdc: null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
Event.$on('region-seleccionada', (region)=> {
|
||||||
|
this.region = region;
|
||||||
|
this.fillGDC(region);
|
||||||
|
this.visible = true;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
methods : {
|
||||||
|
fillGDC(region) {
|
||||||
|
axios.get("/api/grupos-de-compra").then(response => {
|
||||||
|
this.gdcs = response.data[this.region];
|
||||||
|
});
|
||||||
|
},
|
||||||
|
onGDCSelected() {
|
||||||
|
this.isDefaultDisabled = 1;
|
||||||
|
Event.$emit("gdc-seleccionado",this.gdc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
Vue.component('login', {
|
||||||
|
template: `
|
||||||
|
<div v-show="visible" class="block">
|
||||||
|
<div class="field">
|
||||||
|
<label class="label">Contraseña del barrio</label>
|
||||||
|
<p class="control">
|
||||||
|
<input required class="input" type="password" name="password" placeholder="Contraseña del barrio">
|
||||||
|
</p>
|
||||||
|
<p class="help">Si no la sabés, consultá a tus compañerxs.</p>
|
||||||
|
</div>
|
||||||
|
<div class="field">
|
||||||
|
<div class="control">
|
||||||
|
<input type="submit" class="button is-success" value="Ingresar">
|
||||||
|
</input>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>`,
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
visible: false,
|
||||||
|
gdc: null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
Event.$on('gdc-seleccionado', (gdc) => {
|
||||||
|
this.gdc = gdc;
|
||||||
|
this.visible = true;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
new Vue({
|
||||||
|
el: '#root'
|
||||||
|
});
|
171
public/js/productos.js
vendored
Normal file
171
public/js/productos.js
vendored
Normal file
|
@ -0,0 +1,171 @@
|
||||||
|
Vue.component('categorias-container', {
|
||||||
|
template: `
|
||||||
|
<div v-show="visible" class="container">
|
||||||
|
<div class="columns is-multiline is-mobile">
|
||||||
|
<div v-for="catego in categorias" class="block column is-one-quarter-desktop is-one-third-tablet is-half-mobile">
|
||||||
|
<div @click.capture="seleccionarCategoria(catego)" class="card" style="height:100%" >
|
||||||
|
<div class="card-content">
|
||||||
|
<div class="media">
|
||||||
|
<div class="media-content" style="overflow:hidden">
|
||||||
|
<p class="title is-6" v-text="catego"></p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div><!-- END CARD -->
|
||||||
|
</div><!-- END BLOCK COLUMN -->
|
||||||
|
</div><!-- END COLUMNS -->
|
||||||
|
</div><!-- END CONTAINER -->`,
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
categorias: null,
|
||||||
|
visible: true,
|
||||||
|
miga: {
|
||||||
|
nombre: "Categorías",
|
||||||
|
href: "/productos"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
axios.get("/api/categorias").then(response => {
|
||||||
|
this.categorias = response.data;
|
||||||
|
});
|
||||||
|
Event.$emit("migas-setear-como-inicio",this.miga);
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
seleccionarCategoria(categoria) {
|
||||||
|
this.visible = false;
|
||||||
|
Event.$emit("categoria-seleccionada",categoria);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
Vue.component('productos-container', {
|
||||||
|
template: `
|
||||||
|
<div v-show="visible" class="container">
|
||||||
|
<div class="columns is-multiline is-mobile">
|
||||||
|
<div v-for="producto in productos" class="block column is-one-quarter-desktop is-one-third-tablet is-half-mobile">
|
||||||
|
<div @click.capture="seleccionarProducto(producto)" class="card" style="height:100%">
|
||||||
|
<div class="card-image">
|
||||||
|
<figure class="image is-4by3">
|
||||||
|
<img v-bind:src="producto.imagen ? producto.imagen : 'https://bulma.io/images/placeholders/1280x960.png'">
|
||||||
|
</figure>
|
||||||
|
<figure v-show="producto.nacional" class="image icono is-32x32">
|
||||||
|
<img src="/assets/uruguay.png">
|
||||||
|
</figure>
|
||||||
|
<figure v-show="producto.economia_solidaria" class="image icono is-32x32">
|
||||||
|
<img src="/assets/solidaria.png">
|
||||||
|
</figure>
|
||||||
|
</div>
|
||||||
|
<div class="card-content">
|
||||||
|
<div class="media">
|
||||||
|
<div class="media-content">
|
||||||
|
<p class="title is-6" v-text="producto.nombre"></p>
|
||||||
|
<p class="subtitle is-7" v-text="producto.proveedor"></p>
|
||||||
|
<p class="subtitle is-7">$<span v-text="producto.precio"></span></p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div><!-- END CARD -->
|
||||||
|
</div><!-- END BLOCK COLUMN -->
|
||||||
|
</div><!-- END COLUMNS -->
|
||||||
|
</div><!-- END CONTAINER -->`,
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
productos: [],
|
||||||
|
visible: false,
|
||||||
|
categoria: null,
|
||||||
|
paginar: 150
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
miga: function(){
|
||||||
|
return {
|
||||||
|
nombre: this.categoria,
|
||||||
|
href: "#" + this.categoria
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
Event.$on('categoria-seleccionada', (categoria) => {
|
||||||
|
this.categoria = categoria;
|
||||||
|
|
||||||
|
axios.get("/api/productos", {
|
||||||
|
params: {
|
||||||
|
categoria: this.categoria,
|
||||||
|
paginar: this.paginar
|
||||||
|
}
|
||||||
|
}).then(response => {
|
||||||
|
this.productos = response.data.data;
|
||||||
|
});
|
||||||
|
this.visible = true;
|
||||||
|
Event.$emit("migas-agregar",this.miga);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
seleccionarProducto(producto) {
|
||||||
|
Event.$emit("producto-seleccionado",producto);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
Vue.component('producto-container', {
|
||||||
|
template: `
|
||||||
|
<div v-bind:class="visible ? 'is-active modal' : 'modal'">
|
||||||
|
<div class="modal-background"></div>
|
||||||
|
<div class="modal-card">
|
||||||
|
<header class="modal-card-head">
|
||||||
|
<p class="modal-card-title" v-text="producto.nombre"></p>
|
||||||
|
<button class="delete" aria-label="close" @click.capture="cerrar"></button>
|
||||||
|
</header>
|
||||||
|
<section class="modal-card-body">
|
||||||
|
<div class="card-image">
|
||||||
|
<figure class="image is-4by3">
|
||||||
|
<img v-bind:src="producto.imagen ? producto.imagen : 'https://bulma.io/images/placeholders/1280x960.png'">
|
||||||
|
</figure>
|
||||||
|
<figure v-show="producto.nacional" class="image icono is-32x32">
|
||||||
|
<img src="/assets/uruguay.png">
|
||||||
|
</figure>
|
||||||
|
<figure v-show="producto.economia_solidaria" class="image icono is-32x32">
|
||||||
|
<img src="/assets/solidaria.png">
|
||||||
|
</figure>
|
||||||
|
</div>
|
||||||
|
<div class="media-content">
|
||||||
|
<p class="title is-4" v-text="producto.proveedor"></p>
|
||||||
|
<p class="subtitle is-4">$<span v-text="producto.precio"></span></p>
|
||||||
|
<p class="subtitle is-5"><span v-text="producto.descripcion"></span></p>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
<footer class="modal-card-foot">
|
||||||
|
<button class="button is-success">Agregar a la chismosa</button>
|
||||||
|
<button class="button" @click.capture="cerrar">Cancelar</button>
|
||||||
|
</footer>
|
||||||
|
</div>
|
||||||
|
</div>`,
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
producto: null,
|
||||||
|
visible: false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
miga: function(){
|
||||||
|
return {
|
||||||
|
nombre: this.producto.nombre,
|
||||||
|
href: "#" + this.producto.nombre
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
cerrar() {
|
||||||
|
this.visible = false;
|
||||||
|
Event.$emit("migas-pop");
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
Event.$on('producto-seleccionado', (producto) => {
|
||||||
|
this.producto = producto;
|
||||||
|
this.visible = true;
|
||||||
|
Event.$emit("migas-agregar",this.miga);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
33
public/js/subpedidos-create.js
vendored
Normal file
33
public/js/subpedidos-create.js
vendored
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
Vue.component('subpedido-select', {
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
subpedido: null,
|
||||||
|
subpedidosExistentes: []
|
||||||
|
}
|
||||||
|
},
|
||||||
|
props: ["gdcid"],
|
||||||
|
mounted() {
|
||||||
|
console.log("ready");
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
onType() {
|
||||||
|
axios.get("/api/subpedidos?nombre=" + this.subpedido).then(response => {
|
||||||
|
this.subpedidosExistentes = response.data
|
||||||
|
});
|
||||||
|
},
|
||||||
|
submit() {
|
||||||
|
axios.post("/api/subpedidos", {
|
||||||
|
nombre: this.subpedido,
|
||||||
|
grupo_de_compra_id: this.gdcid
|
||||||
|
}).then(response => {
|
||||||
|
|
||||||
|
//se creo el subpedido, guardamos el subpedido en sesion
|
||||||
|
axios.post("/subpedidos/guardar_sesion", {
|
||||||
|
subpedido: response.data
|
||||||
|
}).then(response => {
|
||||||
|
window.location.href = 'productos';
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
|
@ -1,4 +1,45 @@
|
||||||
barrio|region|referente|telefono|correo
|
barrio|region|referente|telefono|correo
|
||||||
ENTREVERO|SUR|||
|
BUCEO|ESTE|||
|
||||||
|
MALVIN NORTE|ESTE|||
|
||||||
|
PINAR|ESTE|||
|
||||||
|
UNION|ESTE|||
|
||||||
|
SANTO DOMINGO|NORTE|||
|
||||||
|
21 DE FEBRERO|NORTE|||
|
||||||
|
PIEDRAS BLANCAS|NORTE|||
|
||||||
|
BELLA ITALIA|NORTE|||
|
||||||
|
JARDINES|NORTE|||
|
||||||
|
LA SOCIALISTA|NORTE|||
|
||||||
|
VILLA GARCIA|NORTE|||
|
||||||
|
LAS ACACIAS|NORTE|||
|
||||||
|
MANGA|NORTE|||
|
||||||
|
CERRITO|OESTE|||
|
||||||
|
LEZICA|OESTE|||
|
||||||
|
PEÑAROL|OESTE|||
|
||||||
|
LAS PIEDRAS|OESTE|||
|
||||||
|
A.C.T.E.O|OESTE|||
|
||||||
|
NUEVO PARIS|OESTE|||
|
||||||
|
SANTA CATALINA|OESTE|||
|
||||||
|
BELVEDERE|OESTE|||
|
||||||
|
BATLLE BERRES|OESTE|||
|
||||||
|
CERRO PTI|OESTE|||
|
||||||
|
COLECTIVO UTU LAVALLEJA|OESTE|||
|
||||||
|
FOGONES|OESTE|||
|
||||||
|
LAVALLEJA|OESTE|||
|
||||||
|
REJUNTE|OESTE|||
|
||||||
|
CAPURRO|OESTE|||
|
||||||
|
PARQUE RODO|SUR|||
|
||||||
|
REDUCTO|SUR|||
|
||||||
|
AGUADA|SUR|||
|
||||||
|
CASA DEL VECINO|SUR|||
|
||||||
|
CIUDAD VIEJA|SUR|||
|
||||||
|
COOP EJIDO|SUR|||
|
||||||
|
COVIREUS|SUR|||
|
||||||
|
LA BLANQUEADA|SUR|||
|
||||||
|
NITEP|SUR|||
|
||||||
|
LA CURVA|SUR|||
|
||||||
|
PANADERIA VIDAL|SUR|||
|
||||||
|
SUA|SUR|||
|
||||||
TRES CRUCES|SUR|||
|
TRES CRUCES|SUR|||
|
||||||
PRUEBA|SIN REGION|||
|
VILLA ESPAÑOLA|SUR|||
|
||||||
|
AUDA|OTRA|||
|
||||||
|
SINTEP|OTRA|||
|
||||||
|
|
|
0
resources/csv/exports/.gitignore
vendored
0
resources/csv/exports/.gitignore
vendored
|
@ -1,381 +1,359 @@
|
||||||
Tipo|Producto|Precio
|
categoria|producto|precio|proveedor
|
||||||
ALIMENTOS NO PERECEDEROS||
|
ALIMENTOS NO PERECEDEROS|Yerba Compuesta La Herboristería 1kg |140.3|
|
||||||
P|Yerba Compuesta La Herboristería 1kg|157.63
|
ALIMENTOS NO PERECEDEROS|Yerba Yusa tradicional 1kg |121.8|
|
||||||
P|Yerba Yusa tradicional 1kg|148.00
|
ALIMENTOS NO PERECEDEROS|Yerba Yusa tradicional 500grs|65|
|
||||||
P|Yerba Yusa tradicional 500grs|81.00
|
ALIMENTOS NO PERECEDEROS|Yerba Sara tradicional 1kg|129.7|
|
||||||
P|Yerba Sara tradicional 1kg (Sin TACC)|139.40
|
ALIMENTOS NO PERECEDEROS|Yerba Sara suave 1kg|132.2|
|
||||||
P|Yerba Sara suave 1kg (Sin TACC)|139.40
|
ALIMENTOS NO PERECEDEROS|Yerba Kiero mate 500grs|72.5|
|
||||||
P|*Harina Santa Unión 000 1kg|33.11
|
ALIMENTOS NO PERECEDEROS|*Harina Santa Unión 000 1kg|27.3|Santa Unión
|
||||||
P|*Harina Santa Unión 0000 1kg|38.70
|
ALIMENTOS NO PERECEDEROS|*Harina Santa Unión 0000 1kg|34.8|Santa Unión
|
||||||
P|*Harina de arroz Pasaná 1 kg (Puede contener gluten)|90.00
|
ALIMENTOS NO PERECEDEROS|*Harina de trigo integral Pasaná 1 kg|65|Pasaná
|
||||||
P|*Harina de Garbanzos Pasaná 1 kg (Puede contener gluten)|140.00
|
ALIMENTOS NO PERECEDEROS|*Harina de arroz Pasaná 1 kg |65|Pasaná
|
||||||
P|*Mezcla para faina Pasaná 1 kg (Puede contener gluten)|160.00
|
ALIMENTOS NO PERECEDEROS|*Harina de Garbanzos Pasaná 1 kg |140|Pasaná
|
||||||
P|*Fécula de Mandioca Pasaná 1 kg (Puede contener gluten)|140.00
|
ALIMENTOS NO PERECEDEROS|*Mezcla para faina Pasaná 1 kg |150|Pasaná
|
||||||
P|Fécula de Mandioca Hornex 800g (Sin TACC)|125.00
|
ALIMENTOS NO PERECEDEROS|*Fécula de Mandioca Pasaná 1 kg |85|Pasaná
|
||||||
P|Tres Harinas Hornex 800grs (Sin TAAC)|129.00
|
ALIMENTOS NO PERECEDEROS|Tres Harinas 500grs. |85|
|
||||||
P|*Harina Santa Unión 000 Bolsa 25kg|602.86
|
ALIMENTOS NO PERECEDEROS|*Harina Santa Unión 000 Bolsa 25kg|560.6|Santa Unión
|
||||||
P|*Polenta Santa Unión 450gr|16.34
|
ALIMENTOS NO PERECEDEROS|*Polenta Santa Unión 450gr|15.4|Santa Unión
|
||||||
P|*Mezcla de Fainá Santa Unión 5kg|431.29
|
ALIMENTOS NO PERECEDEROS|*Mezcla de Fainá Santa Unión 5kg|294.8|Santa Unión
|
||||||
P|*Harina de trigo intergal orgánica "La linda sauceña"|97.00
|
ALIMENTOS NO PERECEDEROS|*Fideos Caorsi Tirabuzón 1kg|59|Caorsi
|
||||||
P|*Fideos Caorsi Tirabuzón 1kg|73.00
|
ALIMENTOS NO PERECEDEROS|*Fideos Caorsi Tallarín 1kg|69|Caorsi
|
||||||
P|*Fideos Caorsi Tallarín 1kg|81.00
|
ALIMENTOS NO PERECEDEROS|*Fideos Caorsi Moñita 1kg|69|Caorsi
|
||||||
P|*Fideos Caorsi Moñita 1kg|81.00
|
ALIMENTOS NO PERECEDEROS|*Fideos Caorsi para sopa 1kg|59|Caorsi
|
||||||
P|*Fideos Caorsi Tirabuzón 5kg|353.00
|
ALIMENTOS NO PERECEDEROS|*Fideos Caorsi para sopa 5kg|268|Caorsi
|
||||||
P|Arroz Blue Patna 1kg|50.02
|
ALIMENTOS NO PERECEDEROS|*Fideos Caorsi Tirabuzón 5kg|268|Caorsi
|
||||||
P|Arroz Shiva 1kg|35.65
|
ALIMENTOS NO PERECEDEROS|Arroz Blue Patna 1kg|40.2|
|
||||||
P|*Arroz integral 1kg|72.00
|
ALIMENTOS NO PERECEDEROS|Arroz Shiva 1kg|27|
|
||||||
P|*Arroz integral 3kg|204.00
|
ALIMENTOS NO PERECEDEROS|Arroz integral 1kg |55|
|
||||||
P|Aceite Condesa de Soja 900 cc.|59.80
|
ALIMENTOS NO PERECEDEROS|Arroz integral 3kg|155|
|
||||||
P|Aceite Uruguay de Girasol 900 cc.|81.70
|
ALIMENTOS NO PERECEDEROS|Aceite Condesa de Soja 900 cc.|84|
|
||||||
P|Aceite Optimo canola 900 cc.|75.00
|
ALIMENTOS NO PERECEDEROS|Aceite Uruguay de Girasol 900 cc.|108|
|
||||||
P|Vinagre Uruguay 900ml|61.60
|
ALIMENTOS NO PERECEDEROS|Aceite Optimo canola 900 cc.|82.4|
|
||||||
P|*Salsa de soja La Posta 250 ml.|120.00
|
ALIMENTOS NO PERECEDEROS|*Aceite de oliva 500 ml. |195|
|
||||||
P|*Aceitunas verdes sin carozo en frasco La Posta 500 gr.|220.00
|
ALIMENTOS NO PERECEDEROS|Vinagre Uruguay 900ml|77.9|
|
||||||
P|*Aceitunas negras sin carozo en frasco La Posta 500 gr.|240.00
|
ALIMENTOS NO PERECEDEROS|Aceite de Oliva Cuatro Piedras 3 lt|1090|
|
||||||
P|Lata de atún Golden Fish desmenuzado al aceite 170g|33.35
|
ALIMENTOS NO PERECEDEROS|*Salsa de soja La Posta 250 ml. |95|
|
||||||
P|Lata de arvejas Campero 300g|18.28
|
ALIMENTOS NO PERECEDEROS|*Aceitunas verdes sin carozo en frasco La Posta 500 gr. |180|La Posta
|
||||||
P|Lata de choclo Cosecha 300g|32.29
|
ALIMENTOS NO PERECEDEROS|*Aceitunas negras sin carozo en frasco frasco La Posta 500 gr. |180|La Posta
|
||||||
P|Lata de jardinera Cosecha|30.34
|
ALIMENTOS NO PERECEDEROS|Lata atún Golden Fish desmenuzado al aceite 170g|31.1|
|
||||||
P|Lata de porotos negros Cosecha|37.06
|
ALIMENTOS NO PERECEDEROS|Lata de arvejas Campero 300g|18.3|
|
||||||
P|Lata de porotos de frutilla Cosecha|37.06
|
ALIMENTOS NO PERECEDEROS|Lata de choclo Cosecha 300g|22|
|
||||||
P|Lata de duraznos en almíbar Campero|73.07
|
ALIMENTOS NO PERECEDEROS|Lata de jardinera Cosecha|25|
|
||||||
P|Mayonesa Uruguay 500g|81.40
|
ALIMENTOS NO PERECEDEROS|Lata de porotos negros Cosecha|31.1|
|
||||||
P|Azúcar Bella Unión 1kg|44.90
|
ALIMENTOS NO PERECEDEROS|Lata de porotos de frutilla Cosecha|31.1|
|
||||||
P|Azúcar Mascabo 500g|102.00
|
ALIMENTOS NO PERECEDEROS|Lata de duraznos en almíbar Campero |66.6|
|
||||||
P|Azúcar impalpable Hornex 200 gr|39.00
|
ALIMENTOS NO PERECEDEROS|Mayonesa Uruguay 500g|77.9|
|
||||||
P|Almidón de maíz Hornex 1Kg|89.00
|
ALIMENTOS NO PERECEDEROS|Azúcar Azucarlito 25kg|1007.5|
|
||||||
P|Almidón de maíz Ilu wayra 1Kg|75.00
|
ALIMENTOS NO PERECEDEROS|Azúcar Bella Unión 1kg|39.8|
|
||||||
P|Polvo de Hornear Hornex 100 g + 20 g|38.00
|
ALIMENTOS NO PERECEDEROS|Azúcar impalpable Hornex 200 gr|31|
|
||||||
P|*Esencia de vainilla La Posta 100ml|100.00
|
ALIMENTOS NO PERECEDEROS|Azúcar impalpable Hornex 1kg|104|
|
||||||
P|*Bicarbonato de sodio La Posta 250 gr|60.00
|
ALIMENTOS NO PERECEDEROS|Almidón de maíz Hornex 1Kg|64.5|
|
||||||
P|Grasa Uruguay 400grs|45.80
|
ALIMENTOS NO PERECEDEROS|Polvo de Hornear Hornex 1 kg|122|
|
||||||
P|Levadura seca Hornex 125g|120.00
|
ALIMENTOS NO PERECEDEROS|Polvo de Hornear Hornex 100 g + 20 g|27.9|
|
||||||
P|Café Sorocabana glaseado p/máquina 500 grs|396.00
|
ALIMENTOS NO PERECEDEROS|*Esencia de vainilla La Posta 100ml|80|
|
||||||
P|Café Sorocabana natural p/máquina 500 grs|557.00
|
ALIMENTOS NO PERECEDEROS|Grasa Uruguay 400grs|50|
|
||||||
P|Café soluble Saint bollón 170 gr|232.50
|
ALIMENTOS NO PERECEDEROS|Levadura seca Hornex 125g|85.5|
|
||||||
P|Té Negro en hebras 90gr hornimans|41.12
|
ALIMENTOS NO PERECEDEROS|Café Sorocabana glaseado p/máquina 500 grs|232.8|
|
||||||
P|Galletas de arroz SIN SAL Natural Rice 120 gr (Sin TACC)|39.00
|
ALIMENTOS NO PERECEDEROS|Café Sorocabana natural p/máquina 500 grs |315.8|
|
||||||
P|Galletas de arroz comunes Natural Rice 120 gr (Sin TACC)|39.00
|
ALIMENTOS NO PERECEDEROS|Café Saint 170 gr Instantaneo|185.3|
|
||||||
P|Leche en polvo entera 250 g|105.00
|
ALIMENTOS NO PERECEDEROS|Té Negro en hebras 90gr hornimans|30.7|
|
||||||
P|Leche en polvo entera 1kg|315.00
|
ALIMENTOS NO PERECEDEROS|Galletas de arroz comunes Natural Rice 120 gr|34|
|
||||||
P|* Coco rallado 200gr|72.00
|
ALIMENTOS NO PERECEDEROS|* Leche en polvo 250grs|65|
|
||||||
P|* Coco rallado 1kg|246.00
|
ALIMENTOS NO PERECEDEROS|* Leche en polvo 1kg|220|
|
||||||
P|Cocoa Hornex 200gr|55.00
|
ALIMENTOS NO PERECEDEROS|* Coco rallado 200gr|70|
|
||||||
P|Postre de chocolate Hornex 8 porciones|44.00
|
ALIMENTOS NO PERECEDEROS|* Coco rallado 1kg|275|
|
||||||
P|Postre LIGHT de vainilla Hornex 8 porciones (aprobado por ADU)|68.00
|
ALIMENTOS NO PERECEDEROS|Cocoa Hornex 200gr|43|
|
||||||
P|Flan de vainilla Hornex 8 porciones|44.00
|
ALIMENTOS NO PERECEDEROS|Postre de chocolate Hornex 8 porciones|36.5|
|
||||||
P|Gelatina de frutilla Hornex 8 porciones|44.00
|
ALIMENTOS NO PERECEDEROS|Prostre LIGHT de vainilla Hornex 8 porciones (aprobado por ADU)|57|
|
||||||
P|Bizcochuelo de vainilla SIN GLUTEN 500gr Hornex|180.00
|
ALIMENTOS NO PERECEDEROS|Flan de vainilla Hornex 8 porciones|36.5|
|
||||||
P|Pizza SIN GLUTEN 320gr Hornex|170.00
|
ALIMENTOS NO PERECEDEROS|Gelatina de frutilla Hornex 8 porciones|36.5|
|
||||||
P|Pulpa de Tomate De Ley 1lt (S-G)|50.43
|
ALIMENTOS NO PERECEDEROS|Bizcochuelo de vainilla SIN GLUTEN 500gr Hornex|142|
|
||||||
P|Pure de papa instantaneo De Ley 125g|24.73
|
ALIMENTOS NO PERECEDEROS|Pizza SIN GLUTEN 320gr Hornex|137|
|
||||||
P|*Sal fina sin fluor Polenteados 500g|36.00
|
ALIMENTOS NO PERECEDEROS|Pulpa de Tomate De Ley 1lt|43.5|
|
||||||
P|*Sal gruesa sin fluor Polenteados 500g|36.00
|
ALIMENTOS NO PERECEDEROS|Pure de papa instantaneo De Ley 125g|21.3|
|
||||||
P|*Sal Rosa 250gr |80.00
|
ALIMENTOS NO PERECEDEROS|*Sal fina sin fluor Polenteados 500g|27|
|
||||||
P|*Salsa de tomate casera (puro tomate) 1 lt - (S-G) - azucar agregada: 1g/L - sal agregada: 0,25g/L|85.00
|
ALIMENTOS NO PERECEDEROS|*Sal gruesa sin fluor Polenteados 500g|27|
|
||||||
P|*Barras de cereales (maní, sésamo, lino, girasol, avena, copos de arroz, copos de máiz, azúcar rubia y miel) - Pack x2|80.00
|
ALIMENTOS NO PERECEDEROS|*Salsa de tomate casera (puro tomate) 1 lt|65|
|
||||||
P|*Barras de cereales bañadas en chocolate (maní, sésamo, lino, girasol, avena, copos de arroz, copos de máiz, azúcar rubia y miel) - Pack x2|90.00
|
ALIMENTOS NO PERECEDEROS|*Barras de cereales (maní, sésamo, lino, girasol, avena, copos de arroz, copos de máiz, azúcar rubia y miel) - Pack x2 |65|
|
||||||
P|*Granola artesanal 500 gr Ing: copos ,avena,miel, vainilla,coco rallado, chia,girasol,sésamo, lino,maní, almendras, castañas de caju, nueces, chips de chocolate.|250.00
|
ALIMENTOS NO PERECEDEROS|*Barras de cereales bañadas en chocolate (maní, sésamo, lino, girasol, avena, copos de arroz, copos de máiz, azúcar rubia y miel) - Pack x2|75|
|
||||||
P|*Granola simple (avena+ girasol+ pasaUva) 1kg|171.00
|
ALIMENTOS NO PERECEDEROS|*Granola artesanal 500 gr Ing: copos ,avena,miel, vainilla,coco rallado, chia,girasol,sésamo, lino,maní, almendras, castañas de caju, nueces, chips de chocolate.|210|
|
||||||
P|*Copos de maíz azucarados 500g|112.00
|
ALIMENTOS NO PERECEDEROS|*Granola simple (avena+ girasol+ pasaUva) 1kg|160|
|
||||||
P|*Copos de maíz naturales 500g|112.00
|
ALIMENTOS NO PERECEDEROS|*Copos de maíz azucarados 500g|89|
|
||||||
P|*Crema untable de maní 330 gr, envase de vidrio |225.00
|
ALIMENTOS NO PERECEDEROS|*Copos de maíz naturales 500g|89|
|
||||||
P|*Tableta artesanal chocolate semiamargo con frutos secos 100g |130.00
|
ALIMENTOS NO PERECEDEROS|*Crema untable de maní 250gr|89|
|
||||||
P|*Tableta artesanal chocolate semiamargo con pasas 100g |130.00
|
ALIMENTOS NO PERECEDEROS|*Galletas de coco, avena y maní 400gr|100|
|
||||||
P|*Tableta artesanal chocolate blanco con frutos secos 100g |130.00
|
ALIMENTOS NO PERECEDEROS|*Budin Panitep con cobertura de chocolate con almendras, maní, nueces y pasas 250grs|160|
|
||||||
P|*Tableta artesanal chocolate blanco con pasas 100g |130.00
|
ALIMENTOS NO PERECEDEROS|*Budin Panitep con cobertura de almíbar y coco con almendras, maní, nueces y pasas 250grs|140|
|
||||||
P|Alfajor de chocolate negro 80 g (S-G) |48.00
|
ALIMENTOS NO PERECEDEROS|*Budin Panitep de naranja 250grs|140|
|
||||||
P|Galletitas dulces de chispas de chocolate y avena 150 g (S-G)|116.00
|
ALIMENTOS NO PERECEDEROS|*Chia 1/4 kg |65|
|
||||||
P|Crackers saladas de sésamo girasol y chía 180 g (S-G)|116.00
|
ALIMENTOS NO PERECEDEROS|*Girasol 1/2 kg |85|
|
||||||
P|*Lino 1/4 kg|42.00
|
ALIMENTOS NO PERECEDEROS|*Lino 1/4 kg |30|
|
||||||
P|*Chía 1/4 kg|80.00
|
ALIMENTOS NO PERECEDEROS|*Sésamo 1/4 kg |55|
|
||||||
P|*Girasol 1/2 kg|140.00
|
ALIMENTOS NO PERECEDEROS|*Quinoa 1 kg |200|
|
||||||
P|*Sésamo 1/4 kg|65.00
|
ALIMENTOS NO PERECEDEROS|*Dátiles con carozo 500 gr|180|
|
||||||
P|*Quinoa 1 kg|210.00
|
ALIMENTOS NO PERECEDEROS|*Cacao en polvo 250 grs |100|
|
||||||
P|*Dátiles con carozo 500 gr|240.00
|
ALIMENTOS NO PERECEDEROS|*Almendra pelada (sin tostar) Polenteados 100g|80|Polenteados
|
||||||
P|*Cacao en polvo 250 grs (S-A)|125.00
|
ALIMENTOS NO PERECEDEROS|*Pasas de Uva Polenteados 250 gr|69|Polenteados
|
||||||
P|*Almendra pelada (sin tostar) Polenteados 100g|93.00
|
ALIMENTOS NO PERECEDEROS|*Nueces Polenteados 100g|79|Polenteados
|
||||||
P|*Pasas de Uva Polenteados 500 gr|149.00
|
ALIMENTOS NO PERECEDEROS|*Castañas tostadas SIN sal 100grs|76|Polenteados
|
||||||
P|*Nueces Polenteados 100g|89.00
|
ALIMENTOS NO PERECEDEROS|*Avena laminada instantánea Polenteados 500g|49|Polenteados
|
||||||
P|*Castañas tostadas SIN sal 100grs|81.00
|
ALIMENTOS NO PERECEDEROS|*Pan de molde Gigor Lacteado 550g|55|Gigor
|
||||||
P|*Avena laminada instantánea Polenteados 500g|69.00
|
ALIMENTOS NO PERECEDEROS|*Pan de molde Gigor Integral 550g|55|Gigor
|
||||||
P|*Pan de molde Gory Lacteado 550g|64.00
|
ALIMENTOS NO PERECEDEROS|*Galleta Malteada La Socialista 350g|56|La Socialista
|
||||||
P|*Pan de molde Integral Gory 550g|64.00
|
ALIMENTOS NO PERECEDEROS|*Galleta Malteada c/semillas (sésamo, chia, lino) La Socialista 380gr |74|La Socialista
|
||||||
P|*Galleta Malteada La Socialista 350g|84.00
|
ALIMENTOS NO PERECEDEROS|*Galleta Cara Sucia La Socialista 350g|63|La Socialista
|
||||||
P|*Galleta Malteada c/semillas (sésamo, chia, lino) La Socialista 380gr|103.00
|
ALIMENTOS NO PERECEDEROS|*Grisines La Socialista 350g|67|La Socialista
|
||||||
P|*Galleta Cara Sucia La Socialista 350g|92.00
|
ALIMENTOS NO PERECEDEROS|*Mezcla para panqueques La Socialista 2 x 250g|56|La Socialista
|
||||||
P|*Grisines La Socialista 350g|96.00
|
ALIMENTOS NO PERECEDEROS|*Mezcla para salsa blanca La Socialista 2 x 50g|46|La Socialista
|
||||||
P|*Maní pelado frito y salado Polenteados 500g|103.00
|
ALIMENTOS NO PERECEDEROS|*Maní pelado frito y salado Polenteados 500g|89|Polenteados
|
||||||
P|*Maní pelado sin sal Polenteados 500g|103.00
|
ALIMENTOS NO PERECEDEROS|*Maní pelado sin sal Polenteados 500g|89|Polenteados
|
||||||
P|*Garbanzo Polenteados 1kg|109.00
|
ALIMENTOS NO PERECEDEROS|*Garbanzo Polenteados 1kg|79|Polenteados
|
||||||
P|* Maiz para pop 500grs|54.00
|
ALIMENTOS NO PERECEDEROS|*Lentejas Polenteados 1kg|96|Polenteados
|
||||||
P|*Lentejas Polenteados 1kg|125.00
|
ALIMENTOS NO PERECEDEROS|*Porotos negros Polenteados 1kg|86|Polenteados
|
||||||
P|*Porotos negros Polenteados 1kg|125.00
|
ALIMENTOS NO PERECEDEROS|*Porotos de manteca Polenteados 1kg |105|Polenteados
|
||||||
P|*Porotos de manteca Polenteados 1kg|149.00
|
ALIMENTOS NO PERECEDEROS|*Proteína de SOJA texturizada 1kg |125|
|
||||||
P|*Porotos mung 1kg |150.00
|
CONDIMENTOS, PERECEDEROS Y BEBIDAS|*Tallarines frescos de yema Pastas Colon 1kg|155|Pastas Colón
|
||||||
P|*Arvejas 1kg |120.00
|
CONDIMENTOS, PERECEDEROS Y BEBIDAS|*Tallarines frescos de espinaca Pastas Colon 1kg|165|Pastas Colón
|
||||||
P|*Proteína de SOJA texturizada 1kg|139.00
|
CONDIMENTOS, PERECEDEROS Y BEBIDAS|*Tallarines frescos de morrón Pastas Colon 1kg|165|Pastas Colón
|
||||||
P|*Semillas Zapallo 100g.|60.00
|
CONDIMENTOS, PERECEDEROS Y BEBIDAS|*Salsa pomarola 300gr ex trabajadores de La Spezia|90|
|
||||||
CONDIMENTOS, PERECEDEROS Y BEBIDAS||
|
CONDIMENTOS, PERECEDEROS Y BEBIDAS|*Fetuccine integral de zanahoria, apto veganos 1kg|190|
|
||||||
P|*Tallarines frescos de yema Pastas Colon 1kg|175.00
|
CONDIMENTOS, PERECEDEROS Y BEBIDAS|*Romanitos rellenos jamón y queso ex trabajadores de La Spezia 1kg|490|
|
||||||
P|*Tallarines frescos de espinaca Pastas Colon 1kg|185.00
|
CONDIMENTOS, PERECEDEROS Y BEBIDAS|*Romanitos vegetarianos ex trabajadores de La Spezia 1kg|490|
|
||||||
P|*Tallarines frescos de morrón Pastas Colon 1kg|190.00
|
CONDIMENTOS, PERECEDEROS Y BEBIDAS|*Sorrentinos jamón y queso 1Kg ex trabajadores de La Spezia|450|
|
||||||
P|*Prepizza 28cm ex trabajadores de La Spezia|90.00
|
CONDIMENTOS, PERECEDEROS Y BEBIDAS|*Sorrentinos Ricota y Nuez 1kg ex Trabajadores de La Spezia|450|
|
||||||
P|*Milanesas de carne 1kg|395.00
|
CONDIMENTOS, PERECEDEROS Y BEBIDAS|*Raviolón vegetariano 1Kg ex trabajadores de La Spezia|450|
|
||||||
P|*Milanesas de pollo 1kg|370.00
|
CONDIMENTOS, PERECEDEROS Y BEBIDAS|*Raviolón Caprese 1kg ex Trabajadores de La Spezia|450|
|
||||||
P|*Empanada de pollo x 6|265.00
|
CONDIMENTOS, PERECEDEROS Y BEBIDAS|*Prepizza de 28cm ex trabajadores de La Spezia|85|
|
||||||
P|*Empanada de carne x 6|265.00
|
CONDIMENTOS, PERECEDEROS Y BEBIDAS|*Milanesas de carne empanadas 1kg|365|
|
||||||
P|*Pan rallado 1kg|75.00
|
CONDIMENTOS, PERECEDEROS Y BEBIDAS|*Milanesas de pollo empanadas 1kg|365|
|
||||||
P|*Pan rallado saborizado 1Kg|95.00
|
CONDIMENTOS, PERECEDEROS Y BEBIDAS|*Milanesas de seitan x6 |300|
|
||||||
P|*Pimienta blanca 30g|20.00
|
CONDIMENTOS, PERECEDEROS Y BEBIDAS|*Hamburguesas parrilleras de soja no transgénica, sal, harina de avena y adobo sin picante x6|300|
|
||||||
P|*Orégano 25g|20.00
|
CONDIMENTOS, PERECEDEROS Y BEBIDAS|*Jamón vegano (gluten de trigo, salsa de tomate, sabor ahumado, sal) horma 250 g|200|
|
||||||
P|*Pimentón 30g|20.00
|
CONDIMENTOS, PERECEDEROS Y BEBIDAS|*Hummus 200cc |140|
|
||||||
P|*Adobo 30g|20.00
|
CONDIMENTOS, PERECEDEROS Y BEBIDAS|*Pate de zanahoria 200cc |140|
|
||||||
P|*Ajo y Perejil 30g|20.00
|
CONDIMENTOS, PERECEDEROS Y BEBIDAS|*Pan rallado 1kg|55|
|
||||||
P|*Clavo de olor 15g|20.00
|
CONDIMENTOS, PERECEDEROS Y BEBIDAS|*Pan rallado saborizado 1Kg|75|
|
||||||
P|*Tomillo 25g|20.00
|
CONDIMENTOS, PERECEDEROS Y BEBIDAS|*Pimienta blanca 30g|20|
|
||||||
P|*PACK "A" Curry / Nuez moscada / Ajo en polvo / Condimento verde / Comino|100.00
|
CONDIMENTOS, PERECEDEROS Y BEBIDAS|*Orégano 25g|20|
|
||||||
P|*PACK "B" Pimienta Negra polvo / Sal de ajo / Aji molido / Canela en polvo / Condimento para arroz|100.00
|
CONDIMENTOS, PERECEDEROS Y BEBIDAS|*Pimentón 30g|20|
|
||||||
P|*PACK "C" Cebolla en polvo / Pimienta blanca en grano / Pimienta negra en grano / Ajo en escamas / Especias surtidas|100.00
|
CONDIMENTOS, PERECEDEROS Y BEBIDAS|*Adobo 30g|20|
|
||||||
P|*Pimentón 250grs|110.00
|
CONDIMENTOS, PERECEDEROS Y BEBIDAS|*Ajo y Perejil 30g|20|
|
||||||
P|*Orégano 250g|115.00
|
CONDIMENTOS, PERECEDEROS Y BEBIDAS|*PACK "A" Curry, nuez moscada, ajo polvo, condimento verde, comino|80|
|
||||||
P|*Nuez moscada entera 2 unidades|28.00
|
CONDIMENTOS, PERECEDEROS Y BEBIDAS|*PACK "B" Pimienta Negra polvo / sal de ajo, aji molido, canela polvo y chimichurry|80|
|
||||||
P|*Canela en rama 10g|25.00
|
CONDIMENTOS, PERECEDEROS Y BEBIDAS|*PACK "C" Cebolla en escamas, tomillo, clavo de olor, pimienta blanca en grano, ajo en escamas|80|
|
||||||
P|*Cúrcuma 20g|25.00
|
CONDIMENTOS, PERECEDEROS Y BEBIDAS|*Pimentón 250grs |75|
|
||||||
P|*Pack "Mix sabores"- Paprika, Albahaca, Mostaza en polvo.|65.00
|
CONDIMENTOS, PERECEDEROS Y BEBIDAS|*Orégano 250g|85|
|
||||||
P|*Pack "Pal mate"- Boldo, Cedron, Marcela.|120.00
|
CONDIMENTOS, PERECEDEROS Y BEBIDAS|*Nuez moscada entera 2 unidades |21|
|
||||||
P|*Pack "Relax"- Tilo, Malva, Té rojo.|120.00
|
CONDIMENTOS, PERECEDEROS Y BEBIDAS|*Canela en rama 10g|21|
|
||||||
P|*Pack "Power" - Ginseng, Carqueja, Ginkgo biloba.|120.00
|
CONDIMENTOS, PERECEDEROS Y BEBIDAS|*Cúrcuma 20g |21|
|
||||||
P|Atado de perejil|50.00
|
CONDIMENTOS, PERECEDEROS Y BEBIDAS|*Pack "Sabores exoticos" - Paprika, fenogreco y cardamomo|57|
|
||||||
P|Mix de hierbas (ciboullete, tomillo, laurel y pasto lim[on)|50.00
|
CONDIMENTOS, PERECEDEROS Y BEBIDAS|'''''''*Pack "Pa''''''''l mate" - Manzanilla, cedrón y carqueja'''''''|105|
|
||||||
P|Atado de romero|50.00
|
CONDIMENTOS, PERECEDEROS Y BEBIDAS|Pack "Medicinas de monte" - Tilo, malva y marcela|105|
|
||||||
P|Fernet 760 ml|405.00
|
CONDIMENTOS, PERECEDEROS Y BEBIDAS|*Pack "Té helado light" - Té rojo, stevia y lemon grass|105|
|
||||||
P|Vino Santero Marselán 1 lt.|235.00
|
CONDIMENTOS, PERECEDEROS Y BEBIDAS|Vino Santero Marselán 1 lt.|198|
|
||||||
P|Frizzante de Maracuyá|246.00
|
CONDIMENTOS, PERECEDEROS Y BEBIDAS|Vino Tannat-Cabernet Paso del Roble 1 lt.|90|
|
||||||
P|Frizzante de Frutos del bosque|246.00
|
CONDIMENTOS, PERECEDEROS Y BEBIDAS|Vino Rosado dulce Paso del Roble 1 lt.|90|
|
||||||
P|*Cerveza artesanal APA Press 1L|170.00
|
CONDIMENTOS, PERECEDEROS Y BEBIDAS|Frizzante de Maracuyá|205|
|
||||||
P|* Cerveza artesanal IPA Press 1L |180.00
|
CONDIMENTOS, PERECEDEROS Y BEBIDAS|Frizzante de Frutos del bosque|205|
|
||||||
P|*Cerveza artesanal Negra Press 1L|180.00
|
CONDIMENTOS, PERECEDEROS Y BEBIDAS|*Cerveza artesanal Sudaka Blonde 500cc|100|
|
||||||
P|* Cerveza artesanal Rubia Lager 1L |160.00
|
CONDIMENTOS, PERECEDEROS Y BEBIDAS|*Cerveza artesanal Sudaka Scottish 500cc|100|
|
||||||
P|Jugo en polvo "Juguito" sabores surtidos|8.00
|
CONDIMENTOS, PERECEDEROS Y BEBIDAS|*Cerveza artesanal Punto Rojo Red Ipa 500cc|100|
|
||||||
P|Jugo Big C 200ml sabores surtidos|16.84
|
CONDIMENTOS, PERECEDEROS Y BEBIDAS|*Cerveza artesanal Punto Rojo Negra 500cc|100|
|
||||||
P|*Refresco U Naranja 2lt|94.00
|
CONDIMENTOS, PERECEDEROS Y BEBIDAS|*Cerveza artesanal APA Guillotina 1L|180|
|
||||||
P|*Refresco U Mandarina 2lt|94.00
|
CONDIMENTOS, PERECEDEROS Y BEBIDAS|Fernet artesanal 780 ml|370|
|
||||||
P|*Refresco U Pomelo 2lt|94.00
|
CONDIMENTOS, PERECEDEROS Y BEBIDAS|Jugo en polvo "Juguito" sabores surtidos|8.06|
|
||||||
P|*Refresco U Limonada 2lt|94.00
|
CONDIMENTOS, PERECEDEROS Y BEBIDAS|Jugo Big C 200ml sabores surtidos|13.14|
|
||||||
P|*Agua 6 lts|98.00
|
CONDIMENTOS, PERECEDEROS Y BEBIDAS|*Refresco U Naranja 2lt|82|
|
||||||
P|*Queso Muzzarella 1/2 kg Unidad Cooperaria|172.00
|
CONDIMENTOS, PERECEDEROS Y BEBIDAS|*Refresco U Mandarina 2lt|82|
|
||||||
P|*Queso Magro s/sal 1/2 kg Unidad Cooperaria|191.00
|
CONDIMENTOS, PERECEDEROS Y BEBIDAS|*Refresco U Pomelo 2lt|82|
|
||||||
P|*Queso Magro c/sal 1/2 kg Unidad Cooperaria|191.00
|
CONDIMENTOS, PERECEDEROS Y BEBIDAS|*Refresco U Limonada 2lt|82|
|
||||||
P|*Queso Danbo 1/2 kg Unidad Cooperaria|188.00
|
CONDIMENTOS, PERECEDEROS Y BEBIDAS|*Agua 6 lts|84|
|
||||||
P|*Queso Sbrinz 1/2 kg Unidad Cooperaria|287.00
|
CONDIMENTOS, PERECEDEROS Y BEBIDAS|*Queso Muzzarella 1/2 kg Unidad Cooperaria|130|
|
||||||
P|*Queso Colonia 1/2 Kg Unidad Cooperaria|197.00
|
CONDIMENTOS, PERECEDEROS Y BEBIDAS|*Queso Magro s/sal 1/2 kg Unidad Cooperaria|147.5|
|
||||||
P|*Queso parrillero 350g Unidad Cooperaria|177.00
|
CONDIMENTOS, PERECEDEROS Y BEBIDAS|*Queso Magro c/sal 1/2 kg Uniddad Cooperaria|147.5|
|
||||||
P|*Queso semiduro 500grs (envasado al vacío) Productores Ismael Cortinas|258.00
|
CONDIMENTOS, PERECEDEROS Y BEBIDAS|*Queso Danbo 1/2 kg Unidad Cooperaria|137.5|
|
||||||
P|*Queso cuartirolo horma 1kg envasado al vacío|375.00
|
CONDIMENTOS, PERECEDEROS Y BEBIDAS|*Queso Sbrinz 1/2 kg Unidad Cooperaria|170|
|
||||||
P|*Queso rallado 200grs|155.00
|
CONDIMENTOS, PERECEDEROS Y BEBIDAS|*Queso Colonia 1/2 Kg Unidad Cooperaria|160|
|
||||||
P|*Dulce de Leche 1 Kg Unidad Cooperaria|269.00
|
CONDIMENTOS, PERECEDEROS Y BEBIDAS|*Queso parrillero 350g Unidad Cooperaria|165|
|
||||||
P|*Morrones en vinagre 330 gr|230.00
|
CONDIMENTOS, PERECEDEROS Y BEBIDAS|*Queso de mandioca en horma 400 gr|200|
|
||||||
P|*Berenjenas en vinagre 330 gr|230.00
|
CONDIMENTOS, PERECEDEROS Y BEBIDAS|*Queso saborizado con ciboulette 600grs (envasado al vacío)|230|
|
||||||
P|*Mermelada de morrones 250 gr|230.00
|
CONDIMENTOS, PERECEDEROS Y BEBIDAS|*Queso saborizado con albahaca 600grs (envasado al vacío)|230|
|
||||||
P|*Mermelada de frutilla, 450 grs.|145.00
|
CONDIMENTOS, PERECEDEROS Y BEBIDAS|*Queso saborizado con orégano 500grs (envasado al vacío)|250|
|
||||||
P|*Mermelada de durazno, 450 grs.|133.00
|
CONDIMENTOS, PERECEDEROS Y BEBIDAS|*Queso semiduro 500grs (envasado al vacío) Productores Ismael Cortinas|195|
|
||||||
P|*Mermelada de ciruela, 450 grs.|133.00
|
CONDIMENTOS, PERECEDEROS Y BEBIDAS|*Queso cuartirolo horma 1kg envasado al vacío|270|
|
||||||
P|*Mermelada de higo, 450 grs.|133.00
|
CONDIMENTOS, PERECEDEROS Y BEBIDAS|*Queso rallado 100grs|63|
|
||||||
P|*Mermelada de zapallo, 450 grs.|133.00
|
CONDIMENTOS, PERECEDEROS Y BEBIDAS|*Queso rallado 200grs|120|
|
||||||
P|*Mermelada de naranja, 450 grs.|134.00
|
CONDIMENTOS, PERECEDEROS Y BEBIDAS|*Dulce de Leche 1 Kg Unidad Cooperaria|165|
|
||||||
P|*Mermelada de arándanos, 450 grs.|159.50
|
CONDIMENTOS, PERECEDEROS Y BEBIDAS|*Dulce de leche de coco 360 gr|300|
|
||||||
P|*Dulce de membrillo, 900grs|123.00
|
CONDIMENTOS, PERECEDEROS Y BEBIDAS|*Morrones en vinagre 330 gr|140|
|
||||||
P|*Dulce de batata con chocolate 1kg|154.00
|
CONDIMENTOS, PERECEDEROS Y BEBIDAS|*Berenjenas en vinagre 330 gr|140|
|
||||||
P|*Dulce de zapallo 1kg|139.00
|
CONDIMENTOS, PERECEDEROS Y BEBIDAS|*Mermelada de morrones 250 gr|140|
|
||||||
P|*Dulce de higo 1kg|134.00
|
CONDIMENTOS, PERECEDEROS Y BEBIDAS|*Mermelada de frutilla, 450 grs. |123|
|
||||||
P|*Miel artesanal 500g|130.00
|
CONDIMENTOS, PERECEDEROS Y BEBIDAS|*Mermelada de durazno, 450 grs.|110|
|
||||||
P|*Miel artesanal 1 kg|240.00
|
CONDIMENTOS, PERECEDEROS Y BEBIDAS|*Mermelada de ciruela, 450 grs. |115|
|
||||||
P|*Canasta de frutas y verduras "34 Sur Productos Orgánicos"|630.00
|
CONDIMENTOS, PERECEDEROS Y BEBIDAS|*Mermelada de higo, 450 grs. |110|
|
||||||
ARTÍCULOS PERSONALES Y DE LIMPIEZA||
|
CONDIMENTOS, PERECEDEROS Y BEBIDAS|*Mermelada de zapallo, 450 grs.|110|
|
||||||
P|Preservativos Prime ultrafinos x3|89.70
|
CONDIMENTOS, PERECEDEROS Y BEBIDAS|*Mermelada de naranja, 450 grs. |115|
|
||||||
P|Preservativos Kamasutra x3|34.00
|
CONDIMENTOS, PERECEDEROS Y BEBIDAS|*Mermelada de arándanos, 450 grs. |145|
|
||||||
P|Tabaco Cerrito|125.67
|
CONDIMENTOS, PERECEDEROS Y BEBIDAS|*Dulce de membrillo, 900grs |105|
|
||||||
P|Hojilla JOB x30|28.36
|
CONDIMENTOS, PERECEDEROS Y BEBIDAS|*Dulce de batata con chocolate 1kg|115|
|
||||||
P|Shampoo Suave 930ml|123.00
|
CONDIMENTOS, PERECEDEROS Y BEBIDAS|*Dulce de zapallo 1kg|115|
|
||||||
P|Acondicionador Suave 930ml|123.00
|
CONDIMENTOS, PERECEDEROS Y BEBIDAS|'''''''*Dulce de higo 1kg'''|115|
|
||||||
P|Jabón de tocador IO, 80gs|16.60
|
CONDIMENTOS, PERECEDEROS Y BEBIDAS|Miel artesanal 1 kg|210|
|
||||||
P|Cepillo dental kolynos máster. |28.00
|
CONDIMENTOS, PERECEDEROS Y BEBIDAS|*Canasta de frutas y verduras "34 Sur Productos Orgánicos"|630|
|
||||||
P|Pasta Dental kolynos 180 grs. |49.00
|
CONDIMENTOS, PERECEDEROS Y BEBIDAS|*Romero 25grs, El Ombú PTIc|45|
|
||||||
P|Pastillas para mosquitos Fuyi x 12|98.30
|
CONDIMENTOS, PERECEDEROS Y BEBIDAS|*Apio 25grs, El Ombú PTIc|45|
|
||||||
P|*Pack x3 jabones glicerina vegetal Natura|380.00
|
CONDIMENTOS, PERECEDEROS Y BEBIDAS|*Menta 25grs, El Ombú PTIc|45|
|
||||||
P|*Shampoo artesanal pelo seco 250ml Natura|250.00
|
CONDIMENTOS, PERECEDEROS Y BEBIDAS|*Melissa 25grs, El Ombú Ptic|45|
|
||||||
P|*Desodorante ecológico apto veganos Natura|190.00
|
CONDIMENTOS, PERECEDEROS Y BEBIDAS|*Albahaca limón, El Ombú Ptic|45|
|
||||||
P|*Shampoo artesanal pelo graso 250ml Natura|250.00
|
CONDIMENTOS, PERECEDEROS Y BEBIDAS|*Llanten 25grs, El Ombú PTIc|45|
|
||||||
P|*Barrita quita manchas 75 gr Natura|100.00
|
ARTÍCULOS PERSONALES Y DE LIMPIEZA|Preservativos Prudence clasico x3|59.09|
|
||||||
P|*Aromatizador ambiental fragancia floral de varilla Natura, 100ml |345.00
|
ARTÍCULOS PERSONALES Y DE LIMPIEZA|Tabaco Cerrito|99|
|
||||||
P|*Aromatizador ambiental fragancia cítrica de varilla Natura, 100ml |345.00
|
ARTÍCULOS PERSONALES Y DE LIMPIEZA|Hojilla JOB x30 |22|
|
||||||
P|*Talco pédico Natura, 200gr|235.00
|
ARTÍCULOS PERSONALES Y DE LIMPIEZA|*Shampoo Ainé Cuidado Total 500cc|230|
|
||||||
P|*Repelente Natura, 125ml|245.00
|
ARTÍCULOS PERSONALES Y DE LIMPIEZA|*Shampoo Ainé Brillo Extremo 500cc|230|
|
||||||
P|*Shampoo pediculosis, envase 250 ml|320.00
|
ARTÍCULOS PERSONALES Y DE LIMPIEZA|*Acondicionador Ainé Cuidado Total 500cc |230|
|
||||||
P|*Jabón en polvo Bonsai 800g|95.00
|
ARTÍCULOS PERSONALES Y DE LIMPIEZA|*Acondicionador Ainé Brillo Extremo 500cc |230|
|
||||||
P|*Jabón en polvo Bonsai 5kg|550.00
|
ARTÍCULOS PERSONALES Y DE LIMPIEZA|*Acondicionador Ainé Dos Minutos 500cc |230|
|
||||||
P|*Suavizante Bonsai 1lt|80.00
|
ARTÍCULOS PERSONALES Y DE LIMPIEZA|Shampoo Suave 930ml |144.09|
|
||||||
P|*Jabon liquido para lavarropas 900 cc Bonsai|85.00
|
ARTÍCULOS PERSONALES Y DE LIMPIEZA|Acondicionador Suave 930ml |144.09|
|
||||||
P|*Jabon liquido para lavarropas 3 lts Bonsai|270.00
|
ARTÍCULOS PERSONALES Y DE LIMPIEZA|Jabón de tocador IO, 80gs |12|
|
||||||
P|*Jabon liquido de Manos 500 cc Bonsai|60.00
|
ARTÍCULOS PERSONALES Y DE LIMPIEZA|Cepillo dental Introdento (medio)|29.74|
|
||||||
P|*Perfumador de telas 250 cc Bonsai|120.00
|
ARTÍCULOS PERSONALES Y DE LIMPIEZA|Pasta Dental Introdento menta 102 grs. |36.72|
|
||||||
P|*Limpiador desengarsante para cocinas y baños aroma cítrico 1 litro (no es para cañerías)|120.00
|
ARTÍCULOS PERSONALES Y DE LIMPIEZA|Loción repelente de mosquitos, 200 ml|210|
|
||||||
P|*Limpiador cremoso 650 cc *|120.00
|
ARTÍCULOS PERSONALES Y DE LIMPIEZA|*Pack x3 jabones glicerina vegetal Natura|330|
|
||||||
P|*Entrebichitos - MEN 2lts. (graseras, pozos, cañerías, plantas)|180.00
|
ARTÍCULOS PERSONALES Y DE LIMPIEZA|*Desodorante ecológico apto veganos Natura|160|
|
||||||
P|*Entrebichitos - MEN Limpieza 1lt (suelos, mesadas, paredes, combate hongos, bacterias y virus)|100.00
|
ARTÍCULOS PERSONALES Y DE LIMPIEZA|*Pasta Dental Libre de Flúor Natura|165|
|
||||||
P|*Entrebichitos - Pastilla grasera|80.00
|
ARTÍCULOS PERSONALES Y DE LIMPIEZA|*Shampoo artesanal pelo graso 250ml Natura|235|
|
||||||
P|*Hipoclorito El Resistente 1800cc|76.00
|
ARTÍCULOS PERSONALES Y DE LIMPIEZA|*Shampoo artesanal pelo seco 250ml Natura|230|
|
||||||
P|*Limpiador perfumado El Resistente (perfumol) 1800cc|76.00
|
ARTÍCULOS PERSONALES Y DE LIMPIEZA|*Shampoo sólido cabello seco y normal 50gr |340|
|
||||||
P|*Detergente El Resistente 500ml|51.00
|
ARTÍCULOS PERSONALES Y DE LIMPIEZA|Protector solar factor 65, 200 ml. NUEVO!!|550|
|
||||||
P|*KIT El Resistente (Hip./Perf./Det.)|188.00
|
ARTÍCULOS PERSONALES Y DE LIMPIEZA|*Shampoo sólido cabello graso 50gr |355|
|
||||||
P|Jabon en barra Primor x1|29.36
|
ARTÍCULOS PERSONALES Y DE LIMPIEZA|*Acondicionador sólido 50gr |350|
|
||||||
P|Rejilla de cocina 40 x 27.5 Tacuabé (ex Paylana) cm|36.00
|
ARTÍCULOS PERSONALES Y DE LIMPIEZA|Cepillo dental de bambú 97% biodegradable (niños y adultos)|165|
|
||||||
P|Trapo de piso 53 x 53 Tacuabé (ex Paylana)|36.00
|
ARTÍCULOS PERSONALES Y DE LIMPIEZA|*Talco pédico 200gr |205|
|
||||||
P|Esponja de cocina|26.00
|
ARTÍCULOS PERSONALES Y DE LIMPIEZA|*Bálsamo labial Herencias de aquelarre (protege y repara) |180|
|
||||||
P|Esponja de acero inoxidable|29.00
|
ARTÍCULOS PERSONALES Y DE LIMPIEZA|*Detergente ecológico grupo Flores Silvestres 500 grs|90|
|
||||||
P|Repasador de algodón 43 x 65 cm|53.00
|
ARTÍCULOS PERSONALES Y DE LIMPIEZA|*Jabón en polvo Bonsai 800g|70|Bonsai
|
||||||
P|Franela 34 x 34|37.00
|
ARTÍCULOS PERSONALES Y DE LIMPIEZA|*Jabón en polvo Bonsai 5kg|350|Bonsai
|
||||||
P|Escoba|116.00
|
ARTÍCULOS PERSONALES Y DE LIMPIEZA|*Suavizante Bonsai 1lt|70|Bonsai
|
||||||
P|Pala con mango|99.00
|
ARTÍCULOS PERSONALES Y DE LIMPIEZA|*Jabon liquido para lavarropas 900 cc Bonsai|80|Bonsai
|
||||||
P|Balde 9 Lts|109.00
|
ARTÍCULOS PERSONALES Y DE LIMPIEZA|*Jabon liquido para lavarropas 3 lts Bonsai|220|Bonsai
|
||||||
P|Bolsa de residuos 50x55 30 unidades|63.00
|
ARTÍCULOS PERSONALES Y DE LIMPIEZA|*Jabon liquido de Manos 500 cc Bonsai|50|Bonsai
|
||||||
P|Lampazo|119.00
|
ARTÍCULOS PERSONALES Y DE LIMPIEZA|*Perfumador de telas 250 cc Bonsai|100|Bonsai
|
||||||
P|Rollitos de aluminio Griselda x12|38.30
|
ARTÍCULOS PERSONALES Y DE LIMPIEZA|*Limpiador desengarsante para cocinas y baños aroma cítrico 1 litro (no es para cañerías)|90|Bonsai
|
||||||
P|rollitos de aluminio jaspe x6|30.00
|
ARTÍCULOS PERSONALES Y DE LIMPIEZA|*Entrebichitos - MEN 2lts. (graseras, pozos, cañerías, plantas)|180|Entrebichitos
|
||||||
P|*Vela de apagón|8.40
|
ARTÍCULOS PERSONALES Y DE LIMPIEZA|*Entrebichitos - MEN Limpieza 1lt (suelos, mesadas, paredes, combate hongos, bacterias y virus)|100|Entrebichitos
|
||||||
P|*Vela de citronela 1 mecha|132.80
|
ARTÍCULOS PERSONALES Y DE LIMPIEZA|*Entrebichitos - Pastilla grasera|80|Entrebichitos
|
||||||
P|Toallita de bebé BabySec ultra 50un|83.00
|
ARTÍCULOS PERSONALES Y DE LIMPIEZA|*Hipoclorito El Resistente 1800cc|66|El Resistente
|
||||||
P|Papel Higienico: Higienol Texturado x4|42.00
|
ARTÍCULOS PERSONALES Y DE LIMPIEZA|*Limpiador perfumado El Resistente (perfumol) 1800cc|66|El Resistente
|
||||||
P|Papel de Cocina Sussex extra x 2 -120 paños-|72.00
|
ARTÍCULOS PERSONALES Y DE LIMPIEZA|*Detergente El Resistente 500ml|43|El Resistente
|
||||||
P|Pañales Babysec ULTRA (Celeste) XXG 24 unidades |448.00
|
ARTÍCULOS PERSONALES Y DE LIMPIEZA|*KIT El Resistente (Hip./Perf./Det.)|161|El Resistente
|
||||||
P|Pañales Babysec ULTRA (Celeste) XG 24 unidades|448.00
|
ARTÍCULOS PERSONALES Y DE LIMPIEZA|Jabon bulldog packx2|66.24|
|
||||||
P|Pañales Babysec ULTRA (Celeste) G 30 unidades|448.00
|
ARTÍCULOS PERSONALES Y DE LIMPIEZA|Rejilla de cocina 40 x 27.5 Tacuabé (ex Paylana) cm|22|
|
||||||
P|Pañales Babysec ULTRA (Celeste) M 36 unidades|448.00
|
ARTÍCULOS PERSONALES Y DE LIMPIEZA|Trapo de piso 55 x 55 Tacuabé (ex Paylana)|35|
|
||||||
P|Pañales Babysec ULTRA (Celeste) P 36 unidades|448.00
|
ARTÍCULOS PERSONALES Y DE LIMPIEZA|Esponja de cocina|22|
|
||||||
P|Pañales Babysec PREMIUM (Violeta) XXG 48 unidades|790.00
|
ARTÍCULOS PERSONALES Y DE LIMPIEZA|Esponja de acero inoxidable|23|
|
||||||
P|Pañales Babysec PREMIUM (Violeta) XG 48 unidades|790.00
|
ARTÍCULOS PERSONALES Y DE LIMPIEZA|Repasador de algodón 43 x 65 cm|39|
|
||||||
P|Pañales Babysec PREMIUM (Violeta) G 60 unidades|790.00
|
ARTÍCULOS PERSONALES Y DE LIMPIEZA|Franela 34 x 34|30|
|
||||||
P|Pañales Babysec PREMIUM (Violeta) M 68 unidades|790.00
|
ARTÍCULOS PERSONALES Y DE LIMPIEZA|Escoba|97|
|
||||||
P|Pañales para Adultes INCOPROTECT TALLE M|579.00
|
ARTÍCULOS PERSONALES Y DE LIMPIEZA|Pala con mango|89|
|
||||||
P|Pañales para Adultes INCOPROTECT TALLE G |617.00
|
ARTÍCULOS PERSONALES Y DE LIMPIEZA|Balde 9 Lts |99|
|
||||||
P|Pañales para Adultes INCOPROTECT TALLE EXTRA G |743.00
|
ARTÍCULOS PERSONALES Y DE LIMPIEZA|Bolsa de residuos 50x55 30 unidades |49|
|
||||||
TEXTIL||
|
ARTÍCULOS PERSONALES Y DE LIMPIEZA|Lampazo |99|
|
||||||
PTC|*Calza licra de algodon talle S|900.00
|
ARTÍCULOS PERSONALES Y DE LIMPIEZA|Guantes de latex talle M|80.1|
|
||||||
PTC|*Calza licra de algodon talle M|900.00
|
ARTÍCULOS PERSONALES Y DE LIMPIEZA|Rollitos de alumnio x6 |27.3|
|
||||||
PTC|*Calza licra de algodon talle L|900.00
|
ARTÍCULOS PERSONALES Y DE LIMPIEZA|*Vela de apagón|8.37|
|
||||||
PTC|*Calza licra de algodon talle XL|900.00
|
ARTÍCULOS PERSONALES Y DE LIMPIEZA|*Vela de citronela 1 mecha|122.2|
|
||||||
PTC|*Biker licra de algodón - Talle S |650.00
|
ARTÍCULOS PERSONALES Y DE LIMPIEZA|Pastillas para mosquitos Sapolio 12 unidades |52.61|
|
||||||
PTC|*Biker licra de algodón - Talle M |650.00
|
ARTÍCULOS PERSONALES Y DE LIMPIEZA|Pañales Babysec ULTRA XXG 24 unidades|312|
|
||||||
PTC|*Biker licra de algodón - Talle L |650.00
|
ARTÍCULOS PERSONALES Y DE LIMPIEZA|Pañales Babysec ULTRA XG 24 unidades|312|
|
||||||
PTC|*Biker licra de algodón - Talle XL |650.00
|
ARTÍCULOS PERSONALES Y DE LIMPIEZA|Pañales Babysec ULTRA G 30 unidades|312|
|
||||||
PTC|*Biker licra de algodón - Talle 0 |350.00
|
ARTÍCULOS PERSONALES Y DE LIMPIEZA|Pañales Babysec ULTRA M 36 unidades|312|
|
||||||
PTC|*Biker licra de algodón - Talle 2 |350.00
|
ARTÍCULOS PERSONALES Y DE LIMPIEZA|Pañales Babysec ULTRA P 36 unidades|312|
|
||||||
PTC|*Biker licra de algodón - Talle 4 |350.00
|
ARTÍCULOS PERSONALES Y DE LIMPIEZA|Toallita de bebé BabySec ultra 50un|67|
|
||||||
PTC|*Biker licra de algodón - Talle 6 |400.00
|
ARTÍCULOS PERSONALES Y DE LIMPIEZA|Papel Higienico: Higienol Texturado x4|47|
|
||||||
PTC|*Biker licra de algodón - Talle 8 |400.00
|
ARTÍCULOS PERSONALES Y DE LIMPIEZA|Papel de Cocina Sussex extra x 2 -120 paños-|57|
|
||||||
PTC|*Biker licra de algodón - Talle 10 |400.00
|
TEXTIL|*Calza licra de algodon talle S|750|
|
||||||
PTC|*Biker licra de algodón - Talle 12 |500.00
|
TEXTIL|*Calza licra de algodon talle M|750|
|
||||||
PTC|*Biker licra de algodón - Talle 14 |500.00
|
TEXTIL|*Calza licra de algodon talle L|750|
|
||||||
PTC|*Biker licra de algodón - Talle 16 |500.00
|
TEXTIL|*Calza licra de algodon talle XL|750|
|
||||||
P|*Conjunto primera muda 100% algodón (pack de pelele, bata y gorrito en bolsa de lienzo) color a elección sujeto a disponibilidad de tela|600.00
|
TEXTIL|*Calza licra de algodon talle 0|300|
|
||||||
PTC|*Calza licra de algodon talle 0|350.00
|
TEXTIL|*Calza licra de algodon talle 2 |300|
|
||||||
PTC|*Calza licra de algodon talle 2|350.00
|
TEXTIL|*Calza licra de algodon talle 4|300|
|
||||||
PTC|*Calza licra de algodon talle 4|350.00
|
TEXTIL|*Calza licra de algodon talle 6 |300|
|
||||||
PTC|*Calza licra de algodon talle 6|450.00
|
TEXTIL|*Calza licra de algodon talle 8 |300|
|
||||||
PTC|*Calza licra de algodon talle 8|450.00
|
TEXTIL|*Calza licra de algodon talle 10|300|
|
||||||
PTC|*Calza licra de algodon talle 10|450.00
|
TEXTIL|*Calza licra de algodon talle 12|300|
|
||||||
PTC|*Calza licra de algodon talle 12|550.00
|
TEXTIL|*Calza licra de algodon talle 14 |350|
|
||||||
PTC|*Calza licra de algodon talle 14|550.00
|
TEXTIL|*Calza licra de algodon talle 16 |350|
|
||||||
PTC|*Calza licra de algodon talle 16|550.00
|
TEXTIL|*Campera deportiva - Talle 0|350|
|
||||||
PTC|*Campera deportiva - Talle 0|400.00
|
TEXTIL|*Campera deportiva - Talle 2|350|
|
||||||
PTC|*Campera deportiva - Talle 2|400.00
|
TEXTIL|*Campera deportiva - Talle 4|350|
|
||||||
PTC|*Campera deportiva - Talle 4|400.00
|
TEXTIL|*Campera deportiva - Talle 6|400|
|
||||||
PTC|*Campera deportiva - Talle 6|450.00
|
TEXTIL|*Campera deportiva - Talle 8|400|
|
||||||
PTC|*Campera deportiva - Talle 8|450.00
|
TEXTIL|*Campera deportiva - Talle 10|400|
|
||||||
PTC|*Campera deportiva - Talle 10|450.00
|
TEXTIL|*Campera deportiva - Talle 12|450|
|
||||||
PTC|*Campera deportiva - Talle 12|500.00
|
TEXTIL|*Campera deportiva - Talle 14|450|
|
||||||
PTC|*Campera deportiva - Talle 14|500.00
|
TEXTIL|*Campera deportiva - Talle 16|450|
|
||||||
PTC|*Campera deportiva - Talle 16|500.00
|
TEXTIL|*Pantalón deportivo - Talle 0|250|
|
||||||
PTC|*Pantalón deportivo - Talle 0|300.00
|
TEXTIL|*Pantalón deportivo - Talle 2|250|
|
||||||
PTC|*Pantalón deportivo - Talle 2|300.00
|
TEXTIL|*Pantalón deportivo - Talle 4|250|
|
||||||
PTC|*Pantalón deportivo - Talle 4|300.00
|
TEXTIL|*Pantalón deportivo - Talle 6|300|
|
||||||
PTC|*Pantalón deportivo - Talle 6|350.00
|
TEXTIL|*Pantalón deportivo - Talle 8|300|
|
||||||
PTC|*Pantalón deportivo - Talle 8|350.00
|
TEXTIL|*Pantalón deportivo - Talle 10|300|
|
||||||
PTC|*Pantalón deportivo - Talle 10|350.00
|
TEXTIL|*Pantalón deportivo - Talle 12|350|
|
||||||
PTC|*Pantalón deportivo - Talle 12|400.00
|
TEXTIL|*Pantalón deportivo - Talle 14|350|
|
||||||
PTC|*Pantalón deportivo - Talle 14|400.00
|
TEXTIL|*Pantalón deportivo - Talle 16|350|
|
||||||
PTC|*Pantalón deportivo - Talle 16|400.00
|
TEXTIL|*Babucha deportiva en algodón - Talle 4|500|
|
||||||
PTC|*Buzo deportivo de verano para adultes - Talle S |1000.00
|
TEXTIL|*Babucha deportiva en algodón - Talle 6|500|
|
||||||
PTC|*Buzo deportivo de verano para adultes - Talle M |1000.00
|
TEXTIL|*Babucha deportiva en algodón - Talle 8 |500|
|
||||||
PTC|*Buzo deportivo de verano para adultes - Talle L |1000.00
|
TEXTIL|*Babucha deportiva en algodón - Talle 10 |600|
|
||||||
PTC|*Buzo deportivo de verano para adultes - Talle XL |1000.00
|
TEXTIL|*Babucha deportiva en algodón - Talle 12 |600|
|
||||||
PTC|*Pantalón deportivo de verano para adultes - Talle S |900.00
|
TEXTIL|*Babucha deportiva en algodón - Talle 14 |600|
|
||||||
PTC|*Pantalón deportivo de verano para adultes - Talle M |900.00
|
TEXTIL|*Babucha deportiva en algodón - Talle 16 |600|
|
||||||
PTC|*Pantalón deportivo de verano para adultes - Talle L |900.00
|
TEXTIL|*Babucha deportiva en algodón - Talle 18 |600|
|
||||||
PTC|*Pantalón deportivo de verano para adultes - Talle XL |900.00
|
TEXTIL|*Pantalón deportivo liso de algodón - Talle S|850|
|
||||||
P|*Juego de sábanas de algodón 1 plaza|1300.00
|
TEXTIL|*Pantalón deportivo liso de algodón - Talle M|850|
|
||||||
P|*Juego de sábanas de algodón 2 plazas (para sommier)|1500.00
|
TEXTIL|*Pantalón deportivo liso de algodón - Talle L|850|
|
||||||
P|*Materas de Lona.|450.00
|
TEXTIL|*Pantalón deportivo liso de algodón - Talle XL |850|
|
||||||
P|*Sábana sola con elástico, 2 plazas (para sommier)|950.00
|
TEXTIL|*Canguro deportivo liso con capucha de algodón - TalleS |1000|
|
||||||
P|*Juego de toallón y toalla de algodón|900.00
|
TEXTIL|*Canguro deportivo liso con capucha de algodón - Talle M |1000|
|
||||||
P|*Toallón|750.00
|
TEXTIL|*Canguro deportivo liso con capucha de algodón - Talle L |1000|
|
||||||
P|*Toalla de mano|350.00
|
TEXTIL|*Canguro deportivo liso con capucha de algodón - Talle XL|1000|
|
||||||
P|*Turbante toalla|450.00
|
TEXTIL|*Túnica niñe con cinto en espalda y tajo detrás- talles 6 a 16|480|
|
||||||
P|*Juego de Sábanas de poliéster 1 plaza |850.00
|
TEXTIL|*Túnica niñe con martingala, festón y pinzas talles 6 a 16|480|
|
||||||
P|*Juego de sábanas de poliéster 2 plazas |1000.00
|
TEXTIL|*Pintor verde - talles 2 a 8|300|
|
||||||
MADRES Y FAMILIARES||
|
TEXTIL|*Pintor azul - talles 2 a 8|300|
|
||||||
PTC|Camiseta EDICION ESPECIAL - talles S al XXL|450.00
|
TEXTIL|*Pintor rojo - talles 2 a 8|300|
|
||||||
PTC|Canguros Madres y Familiares |950.00
|
TEXTIL|*Pintor amarillo - talles 2 a 8|300|
|
||||||
P|Pack 1: 1 pin redondo + 1 lapicera + 1 Pañuelo + Pegotines y marcalibros|150.00
|
TEXTIL|*Túnicas adulto - talles 1 a 5|1100|
|
||||||
P|Pack 2: 1 Pin redondo + 1 Lapicera + Pegotines y marcalibros|100.00
|
TEXTIL|*Moña escolar satinada|50|
|
||||||
P|Pack 3: 1 Llavero + 1 Lapicera|100.00
|
TEXTIL|*Juego de sábanas de algodón 1 plaza|1000|
|
||||||
P|Libro "Desaparecidos"|50.00
|
TEXTIL|*Juego de sábanas de algodón 2 plazas (para sommier) |1200|
|
||||||
ARTÍCULOS DE LA COORDINADORA POR PALESTINA||
|
TEXTIL|*Sábana sola sin elástico, 2 plazas (para sommier) |700|
|
||||||
B|Bono colaboración|20.00
|
TEXTIL|*Sábana sola con elástico, 2 plazas (para sommier) |700|
|
||||||
P|Remera talle S - Palestina|450.00
|
TEXTIL|*Juego de toallón y toalla de algodón |650|
|
||||||
P|Remera talle M - Palestina|450.00
|
TEXTIL|*Toallón|500|
|
||||||
P|Remera talle L - Palestina|450.00
|
TEXTIL|*Toalla de mano|250|
|
||||||
P|Remera talle XL - Palestina|450.00
|
TEXTIL|*Turbante toalla|350|
|
||||||
P|Bandera 60x90 cm - Coordinadora por Palestina|450.00
|
TEXTIL|*Tapaboca de tela|50|
|
||||||
P|Pin Coordinadora por Palestina|40.00
|
ARTÍCULOS DE MADRES Y FAMILIARES|Pañuelo Madres y Familiares de Detenidos Desaparecidos|50|Madres y familiares
|
||||||
P|Balconera "Paremos el genocidio"|150.00
|
ARTÍCULOS DE MADRES Y FAMILIARES|Balconera Madres y Familiares de Detenidos Desaparecidos|100|Madres y familiares
|
||||||
P|Banderita para el auto |100.00
|
ARTÍCULOS DE MADRES Y FAMILIARES|Pack 2 - 1 Pin redondo + Lapicera + Pegotines y Marcalibros|100|Madres y familiares
|
||||||
P|Kit 5 pegotines - Coordinadora por Palestina|80.00
|
PRODUCTOS DEL MPS|Pack de 5 pegotines del MPS (2 logos y 3 consignas, todo a color).|40|Madres y familiares
|
||||||
P|Remera talle S - Palestina - Puño - único color Negro *NUEVO|500.00
|
BONOS Y FINANCIAMIENTO SORORO|Campaña solidaria MPS - apoyo a ollas y merenderos|20|MPS
|
||||||
P|Remera talle M - Palestina - Puño - único color Negro *NUEVO|500.00
|
BONOS Y FINANCIAMIENTO SORORO|Financiamiento sororo para copa menstrual|20|
|
||||||
P|Remera talle L - Palestina - Puño - único color Negro *NUEVO|500.00
|
BONOS Y FINANCIAMIENTO SORORO|Galpón de corrales|20|
|
||||||
P|Remera talle XL - Palestina - Puño - único color Negro *NUEVO|500.00
|
PRODUCTOS DE GESTIÓN MENSTRUAL|Copa menstrual de silicona, ecológica |750|
|
||||||
PRODUCTOS ESPECIALES Y DE FIN DE AÑO||
|
PRODUCTOS DE GESTIÓN MENSTRUAL|Copa menstrual de silicona, ecológica (financiamiento sororo)|0|
|
||||||
P|*Cuaderno artesanal 80 hojas rayado|100.00
|
PRODUCTOS DE GESTIÓN MENSTRUAL|Vaso esterilizador para copa menstrual|290|
|
||||||
P|*Cuaderno artesanal 80 hojas liso|100.00
|
PRODUCTOS DE GESTIÓN MENSTRUAL|*Toallita de tela Nocturna "Chúlin"|170|Chúlin
|
||||||
P|*Cuaderno artesanal 200 hojas rayado|180.00
|
PRODUCTOS DE GESTIÓN MENSTRUAL|*Toallita de tela para Colaless "Chúlin"|170|Chúlin
|
||||||
P|*Cuaderno artesanal 200 hojas liso|180.00
|
PRODUCTOS DE GESTIÓN MENSTRUAL|*Toallitas de tela para Bombacha "Chúlin"|200|Chúlin
|
||||||
P|*Agenda 2025 NUEVO!|420.00
|
PRODUCTOS DE GESTIÓN MENSTRUAL|*Protector Diario de tela "Chúlin"|160|Chúlin
|
||||||
P|Gorro del MPS - Ciudad Vieja NUEVO!|150.00
|
PRODUCTOS DE GESTIÓN MENSTRUAL|*Pack 1: 2 protectores diarios + 2 toallitas para bombacha "Chúlin"|610|Chúlin
|
||||||
P|*Papas con sal 230 gr NUEVO!|154.00
|
PRODUCTOS DE GESTIÓN MENSTRUAL|*Pack 2: 3 protectores diarios "Chúlin" |410|Chúlin
|
||||||
P|*Papas sin sal 250 gr NUEVO!|154.00
|
PRODUCTOS DE GESTIÓN MENSTRUAL|Ladysoft Clasicas 8un|20.3|
|
||||||
P|Turrón Portezuelo Blando 70g NUEVO!|39.67
|
PRODUCTOS DE GESTIÓN MENSTRUAL|Tampones Medianos Ladysoft 10un|84.7|
|
||||||
P|Turrón Portezuelo Bañado 70g NUEVO!|39.67
|
PRODUCTOS DE GESTIÓN MENSTRUAL|Tampones Grandes Ladysoft 10un|84.7|
|
||||||
P |*Budín chocolate 300g NUEVO!|200.00
|
|
||||||
P|*Budín vainilla/cítrico 300g NUEVO!|200.00
|
|
||||||
P|*Budín marmolado 300g NUEVO!|200.00
|
|
||||||
P|Pan dulce artesanal con frutas y pasas 500gms NUEVO!|210.00
|
|
||||||
P|Libro para infancias "Encendiendo Memorias" NUEVO!|350.00
|
|
||||||
TRANSPORTE, BONOS Y FINANCIAMIENTO SORORO||
|
|
||||||
T|Por cada $ 500 de consumo, abonar $ 15 para transporte y gastos operativos, ej:$520 son $30|15.00
|
|
||||||
B|Campaña solidaria MPS - apoyo a ollas y merenderos|30.00
|
|
||||||
B|Financiamiento sororo para copa menstrual|20.00
|
|
||||||
B|Bono especial - Apoyo a la familia del compañero Alberto Colman|20.00
|
|
||||||
B|Bono especial - Apoyo al fletero Ramón|20.00
|
|
||||||
PRODUCTOS SUBSIDIADOS POR FINANCIAMIENTO SORORO||
|
|
||||||
P|*Toallita de tela Nocturna "Chúlin"|210.00
|
|
||||||
P|*Toallita de tela para Colaless "Chúlin"|168.00
|
|
||||||
P|*Toallitas de tela para Bombacha "Chúlin"|175.00
|
|
||||||
P|*Protector Diario de tela "Chúlin"|126.00
|
|
||||||
P|*Pack 1: 2 protectores diarios + 2 toallitas para bombacha "Chúlin"|560.00
|
|
||||||
P|*Pack 2: 3 protectores diarios "Chúlin"|364.00
|
|
||||||
P|Ladysoft Clasicas 8un|27.00
|
|
||||||
P|Tampones algodón orgánico - Talle mini- caja 18 un. |208.00
|
|
||||||
P|Tampones algodón orgánico -Talle medio- caja 18un. |208.00
|
|
||||||
P|Tampones algodón orgánico -Talle super-caja 15 un. |208.00
|
|
||||||
|
|
Can't render this file because it contains an unexpected character in line 19 and column 39.
|
135
resources/js/app.js
vendored
135
resources/js/app.js
vendored
|
@ -3,12 +3,10 @@
|
||||||
* includes Vue and other libraries. It is a great starting point when
|
* includes Vue and other libraries. It is a great starting point when
|
||||||
* building robust, powerful web applications using Vue and Laravel.
|
* building robust, powerful web applications using Vue and Laravel.
|
||||||
*/
|
*/
|
||||||
import axios from 'axios';
|
|
||||||
import Vue from 'vue';
|
require('./bootstrap');
|
||||||
|
|
||||||
window.Vue = require('vue');
|
window.Vue = require('vue');
|
||||||
window.Event = new Vue();
|
|
||||||
window.axios = axios;
|
|
||||||
window.bulmaToast = require('bulma-toast');
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The following block of code may be used to automatically register your
|
* The following block of code may be used to automatically register your
|
||||||
|
@ -17,133 +15,18 @@ window.bulmaToast = require('bulma-toast');
|
||||||
*
|
*
|
||||||
* Eg. ./components/ExampleComponent.vue -> <example-component></example-component>
|
* Eg. ./components/ExampleComponent.vue -> <example-component></example-component>
|
||||||
*/
|
*/
|
||||||
import './components';
|
|
||||||
|
|
||||||
/**
|
// const files = require.context('./', true, /\.vue$/i)
|
||||||
* Constants
|
// files.keys().map(key => Vue.component(key.split('/').pop().split('.')[0], files(key).default))
|
||||||
*/
|
|
||||||
Vue.prototype.$rootMiga = {
|
Vue.component('example-component', require('./components/ExampleComponent.vue').default);
|
||||||
nombre: "Categorías",
|
|
||||||
href: "/productos"
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Global methods
|
|
||||||
*/
|
|
||||||
Vue.prototype.$settearProducto = function(cantidad, id) {
|
|
||||||
Event.$emit("sync-subpedido", this.cant, this.producto.id)
|
|
||||||
}
|
|
||||||
Vue.prototype.$toast = function(mensaje, duration = 2000) {
|
|
||||||
return window.bulmaToast.toast({
|
|
||||||
message: mensaje,
|
|
||||||
duration: duration,
|
|
||||||
type: 'is-danger',
|
|
||||||
position: 'bottom-center',
|
|
||||||
});
|
|
||||||
}
|
|
||||||
Vue.prototype.$limpiarFloat = function(unFloat) {
|
|
||||||
return parseFloat(unFloat.replace(/,/g, ''))
|
|
||||||
}
|
|
||||||
Vue.prototype.$limpiarInt = function(unInt) {
|
|
||||||
return parseInt(unInt.replace(/,/g, ''))
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Next, we will create a fresh Vue application instance and attach it to
|
* Next, we will create a fresh Vue application instance and attach it to
|
||||||
* the page. Then, you may begin adding components to this application
|
* the page. Then, you may begin adding components to this application
|
||||||
* or customize the JavaScript scaffolding to fit your unique needs.
|
* or customize the JavaScript scaffolding to fit your unique needs.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
const app = new Vue({
|
const app = new Vue({
|
||||||
el: '#root',
|
el: '#app',
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
gdc: null,
|
|
||||||
pedido: null,
|
|
||||||
devoluciones: null,
|
|
||||||
}
|
|
||||||
},
|
|
||||||
computed: {
|
|
||||||
productos: function() {
|
|
||||||
return this.pedido.productos
|
|
||||||
}
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
cantidad(producto) {
|
|
||||||
let pedido = this.productos.some(p => p.id == producto.id)
|
|
||||||
return pedido ? this.productos.find(p => p.id == producto.id).pivot.cantidad : 0
|
|
||||||
},
|
|
||||||
notas(producto) {
|
|
||||||
let pedido = this.productos.some(p => p.id == producto.id);
|
|
||||||
return pedido ? this.productos.find(p => p.id == producto.id).pivot.notas : "";
|
|
||||||
},
|
|
||||||
settearDevoluciones() {
|
|
||||||
axios.get(`/api/grupos-de-compra/${this.gdc}/devoluciones`)
|
|
||||||
.then(response => {
|
|
||||||
this.devoluciones = response.data.devoluciones;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
},
|
|
||||||
mounted() {
|
|
||||||
Event.$on('obtener-sesion', () => {
|
|
||||||
axios.get('/subpedidos/obtener_sesion')
|
|
||||||
.then(response => {
|
|
||||||
if (response.data.subpedido.id) {
|
|
||||||
this.gdc = response.data.gdc;
|
|
||||||
this.settearDevoluciones();
|
|
||||||
this.pedido = response.data.subpedido.id;
|
|
||||||
axios.get('/api/subpedidos/' + this.pedido)
|
|
||||||
.then(response => {
|
|
||||||
this.pedido = response.data.data;
|
|
||||||
Event.$emit("pedido-actualizado");
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
axios.get('/admin/obtener_sesion')
|
|
||||||
.then(response => {
|
|
||||||
this.gdc = response.data.gdc
|
|
||||||
});
|
|
||||||
}
|
|
||||||
})
|
|
||||||
})
|
|
||||||
Event.$on('sync-subpedido', (cantidad, id, notas) => {
|
|
||||||
if (this.pedido.aprobado) {
|
|
||||||
this.$toast('No se puede modificar un pedido ya aprobado', 2000);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
axios.post("/api/subpedidos/" + this.pedido.id + "/sync", {
|
|
||||||
cantidad: cantidad,
|
|
||||||
producto_id: id,
|
|
||||||
notas: notas,
|
|
||||||
}).then((response) => {
|
|
||||||
this.pedido = response.data.data
|
|
||||||
this.$toast('Pedido actualizado exitosamente')
|
|
||||||
Event.$emit("pedido-actualizado");
|
|
||||||
});
|
|
||||||
});
|
|
||||||
// Actualizar monto y notas de devoluciones
|
|
||||||
Event.$on('sync-devoluciones', (total, notas) => {
|
|
||||||
if (this.pedido.aprobado) {
|
|
||||||
this.$toast('No se puede modificar un pedido ya aprobado', 2000);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
axios.post("api/subpedidos/" + this.pedido.id + "/sync_devoluciones", {
|
|
||||||
total: total,
|
|
||||||
notas: notas,
|
|
||||||
}).then((response) => {
|
|
||||||
this.pedido = response.data.data;
|
|
||||||
this.$toast('Pedido actualizado');
|
|
||||||
Event.$emit("pedido-actualizado");
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
Event.$on('aprobacion-subpedido', (subpedidoId, aprobado) => {
|
|
||||||
axios.post("/api/admin/subpedidos/" + subpedidoId + "/aprobacion", {
|
|
||||||
aprobacion: aprobado
|
|
||||||
}).then((response) => {
|
|
||||||
Event.$emit('sync-aprobacion', response.data.data);
|
|
||||||
this.$toast('Pedido ' + (aprobado ? 'aprobado' : 'desaprobado') + ' exitosamente')
|
|
||||||
})
|
|
||||||
})
|
|
||||||
Event.$emit('obtener-sesion')
|
|
||||||
},
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
25
resources/js/components.js
vendored
25
resources/js/components.js
vendored
|
@ -1,25 +0,0 @@
|
||||||
import Vue from 'vue';
|
|
||||||
|
|
||||||
const requireComponent = require.context('./components', true, /\.vue$/);
|
|
||||||
|
|
||||||
// Registro automático de componentes:
|
|
||||||
// e.g. components/foo/bar/UnComponente.vue
|
|
||||||
// se registra como 'foo-bar-un-componente'
|
|
||||||
requireComponent.keys().forEach(fileName => {
|
|
||||||
// Get the component config
|
|
||||||
const componentConfig = requireComponent(fileName);
|
|
||||||
// Get the PascalCase name of the component
|
|
||||||
const componentName = fileName
|
|
||||||
.replace(/^\.\/(.*)\.\w+$/, '$1') // Remove "./" from the beginning and the file extension from the end
|
|
||||||
.replace(/\//g, '-') // Replace directories with hyphens
|
|
||||||
.replace(/([a-z])([A-Z])/g, '$1-$2') // Insert hyphen between camelCase words
|
|
||||||
.toLowerCase() // Convert to lowercase
|
|
||||||
// Globally register the component
|
|
||||||
Vue.component(
|
|
||||||
componentName,
|
|
||||||
// Look for the component options on `.default`, which will
|
|
||||||
// exist if the component was exported with `export default`,
|
|
||||||
// otherwise fall back to module's root.
|
|
||||||
componentConfig.default || componentConfig
|
|
||||||
);
|
|
||||||
});
|
|
23
resources/js/components/ExampleComponent.vue
Normal file
23
resources/js/components/ExampleComponent.vue
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
<template>
|
||||||
|
<div class="container">
|
||||||
|
<div class="row justify-content-center">
|
||||||
|
<div class="col-md-8">
|
||||||
|
<div class="card">
|
||||||
|
<div class="card-header">Example Component</div>
|
||||||
|
|
||||||
|
<div class="card-body">
|
||||||
|
I'm an example component.
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
mounted() {
|
||||||
|
console.log('Component mounted.')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
|
@ -1,83 +0,0 @@
|
||||||
<template>
|
|
||||||
<div class="block ml-3 mr-3 is-max-widescreen is-max-desktop">
|
|
||||||
<comunes-tabs-secciones :tabs="tabs" :tabInicial="tabActiva"></comunes-tabs-secciones>
|
|
||||||
<div class="block" id="pedidos-seccion"
|
|
||||||
:class="seccionActiva === 'pedidos-seccion' ? 'is-active' : 'is-hidden'">
|
|
||||||
<div class="block pb-6" id="pedidos-tabla-y-dropdown" v-if="hayPedidos">
|
|
||||||
<admin-dropdown-descargar
|
|
||||||
:gdc_id="gdc.id">
|
|
||||||
</admin-dropdown-descargar>
|
|
||||||
<admin-tabla-pedidos
|
|
||||||
:gdc="this.gdc"
|
|
||||||
></admin-tabla-pedidos>
|
|
||||||
</div>
|
|
||||||
<p class="has-text-centered" v-else>
|
|
||||||
Todavía no hay ningún pedido para administrar.
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
<div class="block pb-6" id="caracteristicas-seccion"
|
|
||||||
:class="seccionActiva === 'caracteristicas-seccion' ? 'is-active' : 'is-hidden'">
|
|
||||||
<admin-caracteristicas-opcionales>
|
|
||||||
</admin-caracteristicas-opcionales>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
import CaracteristicasOpcionales from "./CaracteristicasOpcionales.vue";
|
|
||||||
import TabsSecciones from "../comunes/TabsSecciones.vue";
|
|
||||||
import DropdownDescargar from "./DropdownDescargar.vue";
|
|
||||||
import TablaPedidos from "./TablaPedidos.vue";
|
|
||||||
import TablaBonos from "./TablaBonos.vue";
|
|
||||||
import axios from "axios";
|
|
||||||
export default {
|
|
||||||
components: {
|
|
||||||
CaracteristicasOpcionales,
|
|
||||||
TabsSecciones,
|
|
||||||
DropdownDescargar,
|
|
||||||
TablaPedidos,
|
|
||||||
TablaBonos,
|
|
||||||
},
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
gdc: undefined,
|
|
||||||
tabs: [{ id: "pedidos", nombre: "Pedidos" },
|
|
||||||
{ id: "caracteristicas", nombre: "Caracteristicas opcionales" }],
|
|
||||||
tabActiva: "pedidos",
|
|
||||||
seccionActiva: "pedidos-seccion",
|
|
||||||
}
|
|
||||||
},
|
|
||||||
computed: {
|
|
||||||
hayPedidos: function() {
|
|
||||||
return this.gdc && this.gdc.pedidos.length !== 0
|
|
||||||
},
|
|
||||||
hayAprobados: function() {
|
|
||||||
return this.gdc && this.gdc.pedidos.filter(p => p.aprobado).length > 0
|
|
||||||
}
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
setSeccionActiva(tabId) {
|
|
||||||
this.tabActiva = tabId;
|
|
||||||
this.seccionActiva = tabId + "-seccion";
|
|
||||||
},
|
|
||||||
actualizar() {
|
|
||||||
axios.get('/api/grupos-de-compra/' + this.$root.gdc)
|
|
||||||
.then(response => {
|
|
||||||
this.gdc = response.data.data;
|
|
||||||
console.log(this.gdc);
|
|
||||||
})
|
|
||||||
}
|
|
||||||
},
|
|
||||||
async mounted() {
|
|
||||||
Event.$on('sync-aprobacion', (_) => {
|
|
||||||
this.actualizar();
|
|
||||||
});
|
|
||||||
await new Promise(r => setTimeout(r, 1000));
|
|
||||||
this.actualizar();
|
|
||||||
},
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style>
|
|
||||||
|
|
||||||
</style>
|
|
|
@ -1,12 +0,0 @@
|
||||||
<template>
|
|
||||||
<div class="buttons is-right">
|
|
||||||
<a class="button is-danger is-light is-small" href="/admin">
|
|
||||||
<span class="icon">
|
|
||||||
<i class="fa fa-solid fa-user-check"></i>
|
|
||||||
</span>
|
|
||||||
<span>
|
|
||||||
Admin
|
|
||||||
</span>
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
|
@ -1,42 +0,0 @@
|
||||||
<script>
|
|
||||||
import FilaCaracteristica from "./FilaCaracteristica.vue";
|
|
||||||
|
|
||||||
export default {
|
|
||||||
components: { FilaCaracteristica },
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
caracteristicas: [
|
|
||||||
{
|
|
||||||
id: "devoluciones",
|
|
||||||
nombre: "Devoluciones",
|
|
||||||
habilitada: false
|
|
||||||
},
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<template>
|
|
||||||
<div class="block">
|
|
||||||
<table class="table is-fullwidth is-striped is-bordered">
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th> Característica </th>
|
|
||||||
<th> Habilitada </th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
<admin-fila-caracteristica
|
|
||||||
v-for="(c,i) in caracteristicas"
|
|
||||||
:key="i"
|
|
||||||
:caracteristica="c">
|
|
||||||
</admin-fila-caracteristica>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<style scoped>
|
|
||||||
|
|
||||||
</style>
|
|
|
@ -1,56 +0,0 @@
|
||||||
<template>
|
|
||||||
<div class="buttons is-right">
|
|
||||||
<div class="dropdown" :class="{'is-active': dropdownActivo}" @mouseleave="dropdownActivo = false">
|
|
||||||
<div class="dropdown-trigger">
|
|
||||||
<button class="button" aria-haspopup="true" aria-controls="dropdown-menu" :disabled="!hayAprobados" @click="dropdownActivo = !dropdownActivo">
|
|
||||||
<span class="icon is-small">
|
|
||||||
<i class="fas fa-download"></i>
|
|
||||||
</span>
|
|
||||||
<span>Descargar pedido</span>
|
|
||||||
<span class="icon is-small">
|
|
||||||
<i class="fas fa-angle-down" aria-hidden="true"></i>
|
|
||||||
</span>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
<div class="dropdown-menu" id="dropdown-menu" role="menu">
|
|
||||||
<div class="dropdown-content">
|
|
||||||
<a :href="'/admin/exportar-pedido-a-csv/' + gdc_id" class="dropdown-item has-background-primary">
|
|
||||||
Planilla para central (CSV)
|
|
||||||
</a>
|
|
||||||
<a :href="'/admin/exportar-planillas-a-pdf/' + gdc_id" class="dropdown-item">
|
|
||||||
Planillas para armado (PDF)
|
|
||||||
</a>
|
|
||||||
<a :href="'/admin/exportar-pedido-con-nucleos-a-csv/' + gdc_id" class="dropdown-item">
|
|
||||||
Planilla completa de la canasta (CSV)
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
export default {
|
|
||||||
props: {
|
|
||||||
gdc_id: {
|
|
||||||
type: Number,
|
|
||||||
required: true
|
|
||||||
},
|
|
||||||
},
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
dropdownActivo: false
|
|
||||||
}
|
|
||||||
},
|
|
||||||
computed: {
|
|
||||||
hayAprobados: function() {
|
|
||||||
return this.$parent.hayAprobados;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style>
|
|
||||||
|
|
||||||
</style>
|
|
|
@ -1,69 +0,0 @@
|
||||||
<script>
|
|
||||||
import axios from "axios";
|
|
||||||
|
|
||||||
export default {
|
|
||||||
props: {
|
|
||||||
caracteristica: Object
|
|
||||||
},
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
gdc: undefined
|
|
||||||
}
|
|
||||||
},
|
|
||||||
watch: {
|
|
||||||
'$root.gdc' : {
|
|
||||||
handler(newValue) {
|
|
||||||
if (newValue) {
|
|
||||||
this.gdc = newValue;
|
|
||||||
this.obtenerValor();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
toggleActivacion() {
|
|
||||||
const id = this.caracteristica.id;
|
|
||||||
axios.post(`/api/grupos-de-compra/${this.gdc}/${id}`)
|
|
||||||
.then(response => {
|
|
||||||
this.caracteristica.habilitada = response.data[id];
|
|
||||||
this.$root[id] = response.data[id];
|
|
||||||
});
|
|
||||||
},
|
|
||||||
obtenerValor() {
|
|
||||||
const id = this.caracteristica.id;
|
|
||||||
axios.get(`/api/grupos-de-compra/${this.gdc}/${id}`)
|
|
||||||
.then(response => {
|
|
||||||
this.caracteristica.habilitada = response.data[id];
|
|
||||||
this.$root[id] = response.data[id];
|
|
||||||
});
|
|
||||||
},
|
|
||||||
},
|
|
||||||
mounted() {
|
|
||||||
if (this.$root.gdc) {
|
|
||||||
this.gdc = this.$root.gdc;
|
|
||||||
this.obtenerValor();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<template>
|
|
||||||
<tr>
|
|
||||||
<td>{{ caracteristica.nombre }}</td>
|
|
||||||
<td>
|
|
||||||
<div class="field">
|
|
||||||
<input type="checkbox" class="switch is-rounded is-success"
|
|
||||||
:id="'switch-'+caracteristica.id"
|
|
||||||
:checked="caracteristica.habilitada"
|
|
||||||
@change="toggleActivacion(caracteristica)">
|
|
||||||
<label :for="'switch-'+caracteristica.id">
|
|
||||||
<span class="is-hidden-mobile">{{ caracteristica.habilitada ? 'Habilitada' : 'Deshabilitada' }}</span>
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<style scoped>
|
|
||||||
|
|
||||||
</style>
|
|
|
@ -1,36 +0,0 @@
|
||||||
<template>
|
|
||||||
<tr>
|
|
||||||
<td>{{ pedido.nombre }}</td>
|
|
||||||
<td v-if="$root.devoluciones" class="has-text-right" >{{ pedido.total_sin_devoluciones }}</td>
|
|
||||||
<td v-if="$root.devoluciones" class="has-text-right" ><abbr :title="pedido.devoluciones_notas">-{{ pedido.devoluciones_total }}</abbr></td>
|
|
||||||
<td class="has-text-right" >{{ $root.devoluciones ? pedido.total : pedido.total_sin_devoluciones }}</td>
|
|
||||||
<td>
|
|
||||||
<admin-switch-aprobacion
|
|
||||||
:pedido="pedido">
|
|
||||||
</admin-switch-aprobacion>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
import SwitchAprobacion from "./SwitchAprobacion.vue";
|
|
||||||
export default {
|
|
||||||
components: {
|
|
||||||
SwitchAprobacion
|
|
||||||
},
|
|
||||||
props: {
|
|
||||||
pedido: Object
|
|
||||||
},
|
|
||||||
mounted() {
|
|
||||||
Event.$on('sync-aprobacion', (unPedido) => {
|
|
||||||
if (this.pedido.id === unPedido.id) {
|
|
||||||
this.pedido = unPedido
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style scoped>
|
|
||||||
|
|
||||||
</style>
|
|
|
@ -1,56 +0,0 @@
|
||||||
<template>
|
|
||||||
<div v-show="visible" class="block">
|
|
||||||
<div class="field">
|
|
||||||
<label class="label has-text-white">Contraseña de administración del barrio</label>
|
|
||||||
<div class="field has-addons">
|
|
||||||
<div class="control">
|
|
||||||
<input required class="input" :type="this.passwordType" name="password" placeholder="Contraseña de admin del barrio">
|
|
||||||
</div>
|
|
||||||
<div class="control">
|
|
||||||
<a class="button is-warning" @click="togglePassword">
|
|
||||||
{{ (passwordVisible ? 'Ocultar' : 'Mostrar') + ' contraseña'}}
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<p class="help has-text-white">Si no la sabés, consultá a la comisión informática.</p>
|
|
||||||
</div>
|
|
||||||
<div class="field">
|
|
||||||
<div class="control">
|
|
||||||
<input type="submit" class="button is-warning" value="Ingresar"/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
export default {
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
visible: false,
|
|
||||||
gdc: null,
|
|
||||||
passwordVisible: false,
|
|
||||||
passwordType: "password",
|
|
||||||
}
|
|
||||||
},
|
|
||||||
mounted() {
|
|
||||||
Event.$on('gdc-seleccionado', (gdc) => {
|
|
||||||
this.gdc = gdc;
|
|
||||||
this.visible = true;
|
|
||||||
});
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
togglePassword() {
|
|
||||||
if (this.passwordVisible) this.passwordType = "password";
|
|
||||||
else this.passwordType = "text"
|
|
||||||
this.passwordVisible = !this.passwordVisible
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
|
|
||||||
<style>
|
|
||||||
.help {
|
|
||||||
font-size: 1rem;
|
|
||||||
}
|
|
||||||
</style>
|
|
|
@ -1,46 +0,0 @@
|
||||||
<template>
|
|
||||||
<div class="field">
|
|
||||||
<input type="checkbox" name="switchRoundedSuccess" class="switch is-rounded is-success"
|
|
||||||
:id="'switch'+this.pedido.id"
|
|
||||||
:checked="pedido.aprobado"
|
|
||||||
@change="toggleAprobacion">
|
|
||||||
<label :for="'switch'+this.pedido.id">
|
|
||||||
<span class="is-hidden-mobile">{{ mensaje }}</span>
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
export default {
|
|
||||||
props: {
|
|
||||||
pedido: Object
|
|
||||||
},
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
aprobado: this.pedido.aprobado
|
|
||||||
}
|
|
||||||
},
|
|
||||||
computed: {
|
|
||||||
mensaje: function () {
|
|
||||||
return this.aprobado ? "Pagado" : "No pagado"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
toggleAprobacion() {
|
|
||||||
Event.$emit('aprobacion-subpedido', this.pedido.id, !this.aprobado);
|
|
||||||
this.aprobado = !this.aprobado
|
|
||||||
}
|
|
||||||
},
|
|
||||||
mounted() {
|
|
||||||
Event.$on('sync-aprobacion', (unPedido) => {
|
|
||||||
if (this.pedido.id === unPedido.id) {
|
|
||||||
this.pedido = unPedido
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style scoped>
|
|
||||||
|
|
||||||
</style>
|
|
|
@ -1,97 +0,0 @@
|
||||||
<template>
|
|
||||||
<div class="block">
|
|
||||||
<div class="block" v-show="!hayBonos">
|
|
||||||
<p class="has-text-centered">
|
|
||||||
Todavía no hay bonos pedidos.
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
<div class="block" v-show="hayBonos">
|
|
||||||
<table class="table is-bordered is-striped is-hoverable is-fullwidth">
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th><abbr title="Núcleo">Núcleo</abbr></th>
|
|
||||||
<td v-for="(bono,i) in bonos" :key="i" class="is-1">
|
|
||||||
{{ bono.nombre }}
|
|
||||||
</td>
|
|
||||||
<th><abbr title="Total a Pagar">Total $</abbr></th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
<tr v-for="(bp, i) in bonosPorPedido" :key="i">
|
|
||||||
<td> {{ bp.nucleo }} </td>
|
|
||||||
<td v-for="(bono,j) in bp.bonos" :key="j" class="has-text-right">
|
|
||||||
{{ bono.cantidad }}
|
|
||||||
</td>
|
|
||||||
<td class="has-text-right"> {{ bp.total }} </td>
|
|
||||||
</tr>
|
|
||||||
</tbody>
|
|
||||||
<tfoot>
|
|
||||||
<tr>
|
|
||||||
<th></th>
|
|
||||||
<th :colspan="bonos.length">Total bonos</th>
|
|
||||||
<th class="has-text-right">$ {{ totalBonos }}</th>
|
|
||||||
</tr>
|
|
||||||
</tfoot>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
export default {
|
|
||||||
props: {
|
|
||||||
pedidos: {
|
|
||||||
type: Array,
|
|
||||||
required: true
|
|
||||||
}
|
|
||||||
},
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
bonos: []
|
|
||||||
}
|
|
||||||
},
|
|
||||||
computed: {
|
|
||||||
pedidosAprobados: function() {
|
|
||||||
return this.pedidos.filter(p => p.aprobado)
|
|
||||||
},
|
|
||||||
hayBonos: function() {
|
|
||||||
return this.pedidosAprobados.filter(p => p.subtotal_bonos != 0).length !== 0
|
|
||||||
},
|
|
||||||
bonosPorPedido: function() {
|
|
||||||
let bonosPorPedido = this.pedidosAprobados.map(p => p = {"nucleo":p.nombre, "bonos":p.productos.filter(x => x.bono), "total":p.subtotal_bonos});
|
|
||||||
bonosPorPedido.forEach(bp => {
|
|
||||||
bp.bonos = bp.bonos.map(b => b = {"bono":b.nombre, "cantidad":b.pivot.cantidad, "total":b.pivot.total, "id":b.id})
|
|
||||||
})
|
|
||||||
return bonosPorPedido.map(bp => this.completarBonos(bp));
|
|
||||||
},
|
|
||||||
totalBonos: function() {
|
|
||||||
let total = 0
|
|
||||||
this.bonosPorPedido.map(bp => total += parseInt(bp.total))
|
|
||||||
return total
|
|
||||||
},
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
completarBonos(bonosPedido) {
|
|
||||||
this.bonos.map(b => {
|
|
||||||
if (!bonosPedido.bonos.map(x => x.id).includes(b.id))
|
|
||||||
bonosPedido.bonos.push({"bono":b.nombre, "cantidad":0, "total":0, "id":b.id})
|
|
||||||
})
|
|
||||||
bonosPedido.bonos = bonosPedido.bonos.sort((b1,b2) => b1.id - b2.id)
|
|
||||||
return bonosPedido
|
|
||||||
}
|
|
||||||
},
|
|
||||||
beforeMount() {
|
|
||||||
axios.get("../api/productos", {
|
|
||||||
params: {
|
|
||||||
categoria:'TRANSPORTE, BONOS Y FINANCIAMIENTO SORORO',
|
|
||||||
}
|
|
||||||
}).then(response => {
|
|
||||||
this.bonos = response.data.data;
|
|
||||||
});
|
|
||||||
},
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style>
|
|
||||||
|
|
||||||
</style>
|
|
|
@ -1,69 +0,0 @@
|
||||||
<template>
|
|
||||||
<div>
|
|
||||||
<table class="table is-fullwidth is-striped is-bordered">
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th>Núcleo</th>
|
|
||||||
<th v-if="$root.devoluciones"><abbr title="Total sin tomar en cuenta las devoluciones">Total parcial $</abbr></th>
|
|
||||||
<th v-if="$root.devoluciones"><abbr title="Devoluciones correspondientes al núcleo">Devoluciones $</abbr></th>
|
|
||||||
<th><abbr title="Total a Pagar por el núleo">{{ $root.devoluciones ? 'Total real' : 'Total' }} $</abbr></th>
|
|
||||||
<th class="is-1"><abbr title="Pagado">Pagado</abbr></th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
<admin-fila-pedido
|
|
||||||
v-for="pedido in gdc.pedidos"
|
|
||||||
:pedido="pedido" :key="pedido.id">
|
|
||||||
</admin-fila-pedido>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
<table class="table is-striped is-bordered">
|
|
||||||
<tr>
|
|
||||||
<th colspan="2" class="has-background-black has-text-white has-text-centered">TOTALES</th>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<th>Total a recaudar:</th>
|
|
||||||
<td class="has-text-right">$ {{ gdc.total_a_recaudar }}</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<th>Total bonos barriales:</th>
|
|
||||||
<td class="has-text-right">$ {{ gdc.total_barrial }}</td>
|
|
||||||
</tr>
|
|
||||||
<tr v-if="$root.devoluciones">
|
|
||||||
<th>Total devoluciones:</th>
|
|
||||||
<td class="has-text-right">- $ {{ gdc.total_devoluciones }}</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<th>Cantidad bonos de transporte:</th>
|
|
||||||
<td class="has-text-right">{{ gdc.cantidad_transporte }}</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<th>Total bonos de transporte:</th>
|
|
||||||
<td class="has-text-right">$ {{ gdc.total_transporte }}</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<th>Total a depositar:</th>
|
|
||||||
<td class="has-text-right">$ {{ gdc.total_a_transferir }}</td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
import FilaPedido from "./FilaPedido.vue";
|
|
||||||
export default {
|
|
||||||
components: {
|
|
||||||
FilaPedido
|
|
||||||
},
|
|
||||||
props: {
|
|
||||||
gdc: {
|
|
||||||
type: Object,
|
|
||||||
required: true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style>
|
|
||||||
|
|
||||||
</style>
|
|
|
@ -1,74 +0,0 @@
|
||||||
<template>
|
|
||||||
<div class="block ml-3 mr-3 is-max-widescreen is-max-desktop">
|
|
||||||
<comunes-tabs-secciones :tabs="tabs" :tabInicial="tabActiva"></comunes-tabs-secciones>
|
|
||||||
<div class="block pb-6" id="pedidos-compras-seccion"
|
|
||||||
:class="seccionActiva === 'pedidos-compras-seccion' ? 'is-active' : 'is-hidden'">
|
|
||||||
<div class="block" id="pedidos-compras-tabla-y-dropdown">
|
|
||||||
<compras-dropdown-descargar>
|
|
||||||
</compras-dropdown-descargar>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="block pb-6" id="canasta-compras-seccion"
|
|
||||||
:class="seccionActiva === 'canasta-compras-seccion' ? 'is-active' : 'is-hidden'">
|
|
||||||
<div class="block" id="canasta-compras-seccion">
|
|
||||||
<article class="message is-warning">
|
|
||||||
<div class="message-header">
|
|
||||||
<p>Formato de la canasta</p>
|
|
||||||
</div>
|
|
||||||
<div class="message-body">
|
|
||||||
<div class="content">
|
|
||||||
La planilla de la canasta tiene que tener el siguiente formato para que la aplicación la lea correctamente:
|
|
||||||
<ul>
|
|
||||||
<li> Los precios deben usar punto y no coma decimal </li>
|
|
||||||
<li> El nombre de las columnas deben ser "Tipo", "Producto", y "Precio" respectivamente </li>
|
|
||||||
<li> Las celdas deben separarse con '|' </li>
|
|
||||||
<li> No puede haber "enters" en ninguna celda </li>
|
|
||||||
<li> El bono de transporte debe tener tipo 'T' </li>
|
|
||||||
</ul>
|
|
||||||
<a class="has-text-info" href="/compras/canasta/ejemplo">Planilla de ejemplo.</a>
|
|
||||||
<article class="message is-danger mt-2">
|
|
||||||
<div class="message-body">
|
|
||||||
<div class="content">
|
|
||||||
Cuidado! Cargar una nueva canasta elimina todos los pedidos de la aplicación.
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</article>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</article>
|
|
||||||
<div class="buttons is-right">
|
|
||||||
<compras-canasta-input></compras-canasta-input>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
import TabsSecciones from "../comunes/TabsSecciones.vue";
|
|
||||||
import DropdownDescargar from "./DropdownDescargar.vue";
|
|
||||||
import CanastaInput from "./CanastaInput.vue";
|
|
||||||
|
|
||||||
export default {
|
|
||||||
components: {
|
|
||||||
TabsSecciones,
|
|
||||||
DropdownDescargar,
|
|
||||||
CanastaInput,
|
|
||||||
},
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
tabs: [{ id: "pedidos-compras", nombre: "Pedidos" },
|
|
||||||
{ id: "canasta-compras", nombre: "Canasta" }],
|
|
||||||
tabActiva: "pedidos-compras",
|
|
||||||
seccionActiva: "pedidos-compras-seccion",
|
|
||||||
archivo: undefined,
|
|
||||||
}
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
setSeccionActiva(tabId) {
|
|
||||||
this.tabActiva = tabId;
|
|
||||||
this.seccionActiva = tabId + "-seccion";
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
|
@ -1,69 +0,0 @@
|
||||||
<template>
|
|
||||||
<div class="block">
|
|
||||||
<div class="file has-name is-right">
|
|
||||||
<label class="file-label">
|
|
||||||
<input
|
|
||||||
class="file-input"
|
|
||||||
type="file"
|
|
||||||
name="canasta"
|
|
||||||
@change="archivoSubido"
|
|
||||||
/>
|
|
||||||
<span class="file-cta">
|
|
||||||
<span class="file-icon">
|
|
||||||
<i class="fas fa-cloud-upload-alt"></i>
|
|
||||||
</span>
|
|
||||||
<span class="file-label">Subir canasta</span>
|
|
||||||
</span>
|
|
||||||
<span class="file-name" v-if="archivo">
|
|
||||||
{{ 'Cargando ' + archivo.nombre }}
|
|
||||||
</span>
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
import axios from "axios";
|
|
||||||
|
|
||||||
export default {
|
|
||||||
name: "CanastaInput",
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
archivo: null,
|
|
||||||
cargando: false,
|
|
||||||
};
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
async archivoSubido(event) {
|
|
||||||
const archivo = event.target.files[0];
|
|
||||||
if (archivo && archivo.type === "text/csv") {
|
|
||||||
this.archivo = {data: archivo, nombre: archivo.name};
|
|
||||||
const formData = new FormData();
|
|
||||||
formData.append("data", this.archivo.data);
|
|
||||||
|
|
||||||
try {
|
|
||||||
this.cargando = true;
|
|
||||||
const response = await axios.post("/compras/canasta", formData, {
|
|
||||||
headers: {
|
|
||||||
"Content-Type": "multipart/form-data",
|
|
||||||
},
|
|
||||||
});
|
|
||||||
this.$root.$toast(response.data.message || "Canasta cargada exitosamente");
|
|
||||||
} catch (error) {
|
|
||||||
this.$root.$toast(error.response?.data?.message || "Hubo errores.");
|
|
||||||
} finally {
|
|
||||||
this.cargando = false;
|
|
||||||
this.archivo = null;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
this.$root.$toast("La canasta debe ser .CSV")
|
|
||||||
this.archivo = null;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style scoped>
|
|
||||||
|
|
||||||
</style>
|
|
|
@ -1,44 +0,0 @@
|
||||||
<template>
|
|
||||||
<div class="buttons is-right">
|
|
||||||
<div class="dropdown" :class="{'is-active': dropdownActivo}" @mouseleave="dropdownActivo = false">
|
|
||||||
<div class="dropdown-trigger">
|
|
||||||
<button class="button" aria-haspopup="true" aria-controls="dropdown-menu" @click="dropdownActivo = !dropdownActivo">
|
|
||||||
<span class="icon is-small">
|
|
||||||
<i class="fas fa-download"></i>
|
|
||||||
</span>
|
|
||||||
<span>Descargar planillas</span>
|
|
||||||
<span class="icon is-small">
|
|
||||||
<i class="fas fa-angle-down" aria-hidden="true"></i>
|
|
||||||
</span>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
<div class="dropdown-menu" id="dropdown-menu" role="menu">
|
|
||||||
<div class="dropdown-content">
|
|
||||||
<a href="/compras/pedidos/descargar" class="dropdown-item">
|
|
||||||
Pedidos por barrio
|
|
||||||
</a>
|
|
||||||
<a href="/compras/pedidos/notas" class="dropdown-item">
|
|
||||||
Notas por barrio
|
|
||||||
</a>
|
|
||||||
<a href="/compras/pedidos/pdf" class="dropdown-item">
|
|
||||||
Pedidos por barrio en pdf
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
export default {
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
dropdownActivo: false
|
|
||||||
}
|
|
||||||
},
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style>
|
|
||||||
|
|
||||||
</style>
|
|
|
@ -1,52 +0,0 @@
|
||||||
<template>
|
|
||||||
<div class="block">
|
|
||||||
<div class="field">
|
|
||||||
<label class="label">Usuario</label>
|
|
||||||
<div class="field">
|
|
||||||
<div class="control">
|
|
||||||
<input required class="input" type="text" name="name" placeholder="Usuario">
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="field">
|
|
||||||
<label class="label">Contraseña</label>
|
|
||||||
<div class="field has-addons">
|
|
||||||
<div class="control">
|
|
||||||
<input required class="input" :type="this.passwordType" name="password" placeholder="Contraseña">
|
|
||||||
</div>
|
|
||||||
<div class="control">
|
|
||||||
<a class="button is-dark" @click="togglePassword">
|
|
||||||
{{ (passwordVisible ? 'Ocultar' : 'Mostrar') + ' contraseña'}}
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="field">
|
|
||||||
<div class="control">
|
|
||||||
<input type="submit" class="button is-dark" value="Ingresar"/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
export default {
|
|
||||||
name: "LoginAdmin",
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
passwordVisible: false,
|
|
||||||
passwordType: "password",
|
|
||||||
}
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
togglePassword() {
|
|
||||||
if (this.passwordVisible) this.passwordType = "password";
|
|
||||||
else this.passwordType = "text"
|
|
||||||
this.passwordVisible = !this.passwordVisible
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style>
|
|
||||||
</style>
|
|
|
@ -1,51 +0,0 @@
|
||||||
<template>
|
|
||||||
<div v-show="visible" class="block">
|
|
||||||
<div class="field">
|
|
||||||
<label class="label" :class="isAdmin ? 'has-text-white' : ''">Seleccioná tu barrio o grupo de compra</label>
|
|
||||||
<div class="control">
|
|
||||||
<div class="select">
|
|
||||||
<select @change="onGDCSelected" v-model="gdc" name="name">
|
|
||||||
<option :disabled="isDefaultDisabled==1" value=null>Seleccionar</option>
|
|
||||||
<option v-for="(gdc, index) in gdcs" :key="index" v-text="gdc.nombre + (isAdmin ? '_admin' : '')"
|
|
||||||
:name="gdc.nombre + (isAdmin ? '_admin' : '')">
|
|
||||||
</option>
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
export default {
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
visible: false,
|
|
||||||
region: null,
|
|
||||||
gdcs: [],
|
|
||||||
isDefaultDisabled: 0,
|
|
||||||
gdc: null,
|
|
||||||
isAdmin: this.admin == null ? false : this.admin
|
|
||||||
}
|
|
||||||
},
|
|
||||||
mounted() {
|
|
||||||
Event.$on('region-seleccionada', (region)=> {
|
|
||||||
this.region = region;
|
|
||||||
this.fillGDC(region);
|
|
||||||
this.visible = true;
|
|
||||||
});
|
|
||||||
},
|
|
||||||
methods : {
|
|
||||||
fillGDC(region) {
|
|
||||||
axios.get("/api/grupos-de-compra").then(response => {
|
|
||||||
this.gdcs = response.data[this.region];
|
|
||||||
});
|
|
||||||
},
|
|
||||||
onGDCSelected() {
|
|
||||||
this.isDefaultDisabled = 1;
|
|
||||||
Event.$emit("gdc-seleccionado",this.gdc);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
props: {'admin': Boolean}
|
|
||||||
}
|
|
||||||
</script>
|
|
|
@ -1,91 +0,0 @@
|
||||||
<template>
|
|
||||||
<nav id="nav-bar" class="navbar is-danger is-fixed-top" role="navigation" aria-label="main navigation">
|
|
||||||
<div class="navbar-brand">
|
|
||||||
<a class="navbar-item" href="https://mps.org.uy">
|
|
||||||
<img src="/assets/logoMPS.png" height="28">
|
|
||||||
</a>
|
|
||||||
<!-- Styles nombre del barrio-->
|
|
||||||
<p class="navbar-item hide-below-1024">
|
|
||||||
<slot name="gdc"></slot>
|
|
||||||
</p>
|
|
||||||
<p class="navbar-item">
|
|
||||||
<slot name="subpedido"></slot>
|
|
||||||
</p>
|
|
||||||
<pedidos-chismosa-dropdown v-if="this.$root.pedido != null" class="hide-above-1023" id="mobile"></pedidos-chismosa-dropdown>
|
|
||||||
<a role="button" class="navbar-burger" :class="{'is-active':burgerActiva}" aria-label="menu" aria-expanded="false" data-target="nav-bar" @click="toggleBurger">
|
|
||||||
<span aria-hidden="true"></span>
|
|
||||||
<span aria-hidden="true"></span>
|
|
||||||
<span aria-hidden="true"></span>
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
<div class="navbar-menu" :class="{'is-active':burgerActiva}">
|
|
||||||
<div class="navbar-end">
|
|
||||||
<div v-if="this.$root.pedido != null" class="navbar-item field has-addons mt-2 mr-3">
|
|
||||||
<a class="button is-small has-text-dark-grey" @click.capture="buscar">
|
|
||||||
<span class="icon">
|
|
||||||
<i class="fas fa-search"></i>
|
|
||||||
</span>
|
|
||||||
</a>
|
|
||||||
<input class="input is-small" type="text" placeholder="Harina" v-model="searchString" @keyup.enter="buscar" >
|
|
||||||
</div>
|
|
||||||
<pedidos-chismosa-dropdown v-if="this.$root.pedido != null" class="hide-below-1024" id="wide"></pedidos-chismosa-dropdown>
|
|
||||||
<div class="block navbar-item">
|
|
||||||
<a onclick="event.preventDefault(); document.getElementById('logout-form').submit();" class="text-a">
|
|
||||||
Cerrar sesión
|
|
||||||
</a>
|
|
||||||
<slot name="logout-form"></slot>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</nav>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
import ChismosaDropdown from '../pedidos/ChismosaDropdown.vue';
|
|
||||||
export default {
|
|
||||||
components: { ChismosaDropdown },
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
burgerActiva: false,
|
|
||||||
searchString: "",
|
|
||||||
}
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
toggleBurger() {
|
|
||||||
this.burgerActiva = !this.burgerActiva
|
|
||||||
},
|
|
||||||
buscar() {
|
|
||||||
if (this.burgerActiva) this.toggleBurger()
|
|
||||||
Event.$emit("migas-setear-como-inicio", this.$rootMiga)
|
|
||||||
Event.$emit("filtrar-productos",'nombre',this.searchString)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style>
|
|
||||||
|
|
||||||
p.navbar-item:empty {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
#nav-bar {
|
|
||||||
z-index: 10;
|
|
||||||
}
|
|
||||||
|
|
||||||
.text-a {
|
|
||||||
color: inherit;
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (max-width: 1023px) {
|
|
||||||
.hide-below-1024 {
|
|
||||||
display: none !important;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (min-width: 1024px) {
|
|
||||||
.hide-above-1023 {
|
|
||||||
display: none !important;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
|
@ -1,38 +0,0 @@
|
||||||
<template>
|
|
||||||
<div class="block">
|
|
||||||
<div class="field">
|
|
||||||
<label class="label" :class="whiteText ? 'has-text-white' : ''">Seleccioná tu región</label>
|
|
||||||
<div class="control">
|
|
||||||
<div class="select">
|
|
||||||
<select @change="onRegionSelected" v-model="region">
|
|
||||||
<option :disabled="isDefaultDisabled===1" value=null>Seleccionar</option>
|
|
||||||
<option v-for="(region, index) in regiones" :key="index" v-text="region" :name="region"></option>
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
export default {
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
regiones: [],
|
|
||||||
isDefaultDisabled: 0,
|
|
||||||
region: null,
|
|
||||||
whiteText: this.admin == null ? false : this.admin
|
|
||||||
}
|
|
||||||
},
|
|
||||||
mounted() {
|
|
||||||
axios.get("/api/regiones").then(response => this.regiones = response.data);
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
onRegionSelected() {
|
|
||||||
this.isDefaultDisabled = 1;
|
|
||||||
Event.$emit("region-seleccionada",this.region);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
props: {'admin': Boolean}
|
|
||||||
}
|
|
||||||
</script>
|
|
|
@ -1,55 +0,0 @@
|
||||||
<template>
|
|
||||||
<div class="block">
|
|
||||||
<div class="tabs is-boxed" id="tabs">
|
|
||||||
<ul class="has-bottom-line">
|
|
||||||
<li v-for="(tab, index) in tabs" class="is-size-6"
|
|
||||||
:key="index"
|
|
||||||
:id="tab.id + '-tab'"
|
|
||||||
:class="{'is-active': tab.id === tabActiva}">
|
|
||||||
<a @click="setTabActiva(tab.id)">
|
|
||||||
<span>
|
|
||||||
{{ tab.nombre }}
|
|
||||||
</span>
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
export default {
|
|
||||||
props: {
|
|
||||||
tabs: Array,
|
|
||||||
tabInicial: String,
|
|
||||||
},
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
tabActiva: this.tabInicial,
|
|
||||||
}
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
setTabActiva(tabId) {
|
|
||||||
this.$parent.setSeccionActiva(tabId);
|
|
||||||
this.tabActiva = tabId
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
|
||||||
@import '../../../../node_modules/bulma';
|
|
||||||
hr {
|
|
||||||
border: none;
|
|
||||||
height: 1px;
|
|
||||||
}
|
|
||||||
.has-bottom-line {
|
|
||||||
border-bottom-color: #dbdbdb !important;
|
|
||||||
border-bottom-style: solid !important;
|
|
||||||
border-bottom-width: 1px !important;
|
|
||||||
}
|
|
||||||
.tabs li.is-active a {
|
|
||||||
border-bottom-color: #e3342f;
|
|
||||||
color: #e3342f;
|
|
||||||
}
|
|
||||||
</style>
|
|
|
@ -1,22 +0,0 @@
|
||||||
<template>
|
|
||||||
<div class="columns ml-3 mr-3">
|
|
||||||
<pedidos-categorias-container :class="chismosaActiva ? 'hide-below-1024' : ''"></pedidos-categorias-container>
|
|
||||||
<pedidos-productos-container :class="chismosaActiva ? 'hide-below-1024' : ''"></pedidos-productos-container>
|
|
||||||
<pedidos-chismosa v-show="chismosaActiva"></pedidos-chismosa>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
export default {
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
chismosaActiva: false,
|
|
||||||
}
|
|
||||||
},
|
|
||||||
mounted() {
|
|
||||||
Event.$on('toggle-chismosa', (activa) => {
|
|
||||||
this.chismosaActiva = activa;
|
|
||||||
});
|
|
||||||
},
|
|
||||||
}
|
|
||||||
</script>
|
|
|
@ -1,32 +0,0 @@
|
||||||
<template>
|
|
||||||
<div v-show="aprobado" class="notification is-warning has-text-centered">
|
|
||||||
Tu pedido fue <strong>aprobado</strong>, por lo que no puede ser modificado
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
export default {
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
aprobado: false,
|
|
||||||
}
|
|
||||||
},
|
|
||||||
mounted() {
|
|
||||||
Event.$on('pedido-actualizado', this.actualizarEstado);
|
|
||||||
if (this.$root.pedido != null) {
|
|
||||||
this.actualizarEstado();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
pedidoAprobado: function() {
|
|
||||||
return this.$root.pedido.aprobado;
|
|
||||||
},
|
|
||||||
actualizarEstado: function() {
|
|
||||||
this.aprobado = this.pedidoAprobado();
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style>
|
|
||||||
</style>
|
|
|
@ -1,41 +0,0 @@
|
||||||
<template>
|
|
||||||
<div v-show="visible" class="column">
|
|
||||||
<div class="columns is-multiline is-mobile">
|
|
||||||
<div v-for="(categoria,i) in categorias" :key="i" class="block column is-one-quarter-desktop is-one-third-tablet is-half-mobile">
|
|
||||||
<div @click.capture="seleccionarCategoria(categoria)" class="card" style="height:100%" >
|
|
||||||
<div class="card-content">
|
|
||||||
<div class="media">
|
|
||||||
<div class="media-content" style="overflow:hidden">
|
|
||||||
<p class="title is-6" v-text="categoria"></p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div><!-- END CARD -->
|
|
||||||
</div><!-- END BLOCK COLUMN -->
|
|
||||||
</div><!-- END COLUMNS -->
|
|
||||||
</div><!-- END CONTAINER -->
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
export default {
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
categorias: null,
|
|
||||||
visible: true
|
|
||||||
}
|
|
||||||
},
|
|
||||||
mounted() {
|
|
||||||
axios.get("/api/categorias").then(response => {
|
|
||||||
this.categorias = response.data;
|
|
||||||
});
|
|
||||||
Event.$emit("migas-setear-como-inicio", this.$rootMiga);
|
|
||||||
Event.$on("filtrar-productos", (_) => this.visible = false)
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
seleccionarCategoria(categoria) {
|
|
||||||
this.visible = false;
|
|
||||||
Event.$emit("filtrar-productos",'categoria',categoria);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
|
@ -1,102 +0,0 @@
|
||||||
<template>
|
|
||||||
<div class="column is-one-third">
|
|
||||||
<div class="fixed-right">
|
|
||||||
<table v-show="mostrar_tabla" class="table is-striped is-bordered tabla-chismosa is-narrow">
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th>Producto</th>
|
|
||||||
<th>Cantidad</th>
|
|
||||||
<th><abbr title="Precio Total">$</abbr></th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tfoot>
|
|
||||||
<tr>
|
|
||||||
<th><abbr title="Bonos de Transporte">B. Transporte</abbr></th>
|
|
||||||
<th class="has-text-right">{{ cantidad_bonos_transporte }}</th>
|
|
||||||
<th class="has-text-right">{{ total_bonos_transporte }}</th>
|
|
||||||
</tr>
|
|
||||||
<tr v-if="this.$root.devoluciones">
|
|
||||||
<th><p>Devoluciones</p></th>
|
|
||||||
<td>
|
|
||||||
<abbr :title="notas_devoluciones">{{ notas_devoluciones_abbr }}</abbr>
|
|
||||||
<button @click.capture="modificarDevoluciones()" class="button is-warning is-small">
|
|
||||||
<span class="icon">
|
|
||||||
<i class="fas fa-edit"></i>
|
|
||||||
</span>
|
|
||||||
</button>
|
|
||||||
</td>
|
|
||||||
<th class="has-text-right">-{{ devoluciones }}</th>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<th>Total total</th>
|
|
||||||
<th></th>
|
|
||||||
<th class="has-text-right">{{ total }}</th>
|
|
||||||
</tr>
|
|
||||||
</tfoot>
|
|
||||||
<tbody>
|
|
||||||
<pedidos-producto-row v-for="producto in productos" :producto="producto" :key="producto.id"></pedidos-producto-row>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
<p class="has-text-centered" v-show="!mostrar_tabla">
|
|
||||||
Compa, todavía no agregaste nada a la chismosa.
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
export default {
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
mostrar_tabla: false,
|
|
||||||
cantidad_bonos_transporte: 0,
|
|
||||||
total_bonos_transporte: 0,
|
|
||||||
devoluciones: 0,
|
|
||||||
notas_devoluciones: "",
|
|
||||||
notas_devoluciones_abbr: "",
|
|
||||||
total: 0,
|
|
||||||
productos: [],
|
|
||||||
}
|
|
||||||
},
|
|
||||||
mounted() {
|
|
||||||
Event.$on('pedido-actualizado', this.pedidoActualizado);
|
|
||||||
Event.$on('toggle-chismosa', this.pedidoActualizado);
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
pedidoActualizado: function() {
|
|
||||||
this.mostrar_tabla = this.$root.productos.length > 0;
|
|
||||||
this.cantidad_bonos_transporte = this.cantidadBonosDeTransporte();
|
|
||||||
this.total_bonos_transporte = this.totalBonosDeTransporte();
|
|
||||||
this.devoluciones = this.$root.pedido.devoluciones_total;
|
|
||||||
this.notas_devoluciones = this.$root.pedido.devoluciones_notas;
|
|
||||||
this.notas_devoluciones_abbr = this.notas_devoluciones.substring(0, 15);
|
|
||||||
if (this.notas_devoluciones.length > 15) {
|
|
||||||
this.notas_devoluciones_abbr += "...";
|
|
||||||
}
|
|
||||||
this.total = this.$root.pedido.total;
|
|
||||||
this.productos = this.$root.productos;
|
|
||||||
},
|
|
||||||
modificarDevoluciones: function() {
|
|
||||||
Event.$emit("modificar-devoluciones");
|
|
||||||
},
|
|
||||||
cantidadBonosDeTransporte: function() {
|
|
||||||
return this.$root.pedido.cantidad_transporte;
|
|
||||||
},
|
|
||||||
totalBonosDeTransporte: function() {
|
|
||||||
return this.$root.pedido.total_transporte
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style>
|
|
||||||
.tabla-chismosa {
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
.fixed-right {
|
|
||||||
position: fixed;
|
|
||||||
overflow-y: auto;
|
|
||||||
max-height: 81vh;
|
|
||||||
margin-right: 20px;
|
|
||||||
}
|
|
||||||
</style>
|
|
|
@ -1,45 +0,0 @@
|
||||||
<template>
|
|
||||||
<div class="dropdown is-right navbar-item" :class="{'is-active':activa}">
|
|
||||||
<div class="dropdown-trigger">
|
|
||||||
<a class="text-a" aria-haspopup="true" :aria-controls="id" @click.capture="toggle">
|
|
||||||
<span class="icon is-small mr-1">
|
|
||||||
<img src="/assets/chismosa.png">
|
|
||||||
</span>
|
|
||||||
<span v-text="'$' + total"></span>
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
import Chismosa from './Chismosa.vue'
|
|
||||||
export default {
|
|
||||||
components: {
|
|
||||||
Chismosa
|
|
||||||
},
|
|
||||||
props: {
|
|
||||||
id: {
|
|
||||||
type: String,
|
|
||||||
required: true
|
|
||||||
}
|
|
||||||
},
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
activa: false,
|
|
||||||
total: 0,
|
|
||||||
}
|
|
||||||
},
|
|
||||||
mounted() {
|
|
||||||
Event.$on('pedido-actualizado', this.actualizar);
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
toggle() {
|
|
||||||
this.activa = !this.activa;
|
|
||||||
Event.$emit("toggle-chismosa", this.activa);
|
|
||||||
},
|
|
||||||
actualizar() {
|
|
||||||
this.total = this.$root.pedido.total;
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
</script>
|
|
|
@ -1,67 +0,0 @@
|
||||||
<template>
|
|
||||||
<div v-bind:class="visible ? 'is-active modal' : 'modal'">
|
|
||||||
<div class="modal-background"></div>
|
|
||||||
<div class="modal-card">
|
|
||||||
<header class="modal-card-head">
|
|
||||||
<p class="modal-card-title">Devoluciones</p>
|
|
||||||
<button class="delete" aria-label="close" @click.capture="cerrar"></button>
|
|
||||||
</header>
|
|
||||||
<section class="modal-card-body">
|
|
||||||
<div class="field has-addons is-centered is-thin-centered">
|
|
||||||
<p class="control">
|
|
||||||
Total:
|
|
||||||
<input id="total" class="input" type="number" v-model="total" style="text-align: center">
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
<div class="field has-addons is-centered is-thin-centered">
|
|
||||||
<p class="control">
|
|
||||||
Notas:
|
|
||||||
<input id="notas" class="input" type="text" v-model.text="notas">
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
<footer class="modal-card-foot">
|
|
||||||
<button class="button is-success" @click="modificar">Aceptar</button>
|
|
||||||
<button class="button" @click.capture="cerrar">Cancelar</button>
|
|
||||||
</footer>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
export default {
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
visible: false,
|
|
||||||
total: 0,
|
|
||||||
notas: "",
|
|
||||||
}
|
|
||||||
},
|
|
||||||
computed: {
|
|
||||||
miga: function() {
|
|
||||||
return {
|
|
||||||
nombre: "Devoluciones",
|
|
||||||
href: "#devoluciones",
|
|
||||||
}
|
|
||||||
},
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
cerrar() {
|
|
||||||
this.visible = false;
|
|
||||||
Event.$emit("migas-pop");
|
|
||||||
},
|
|
||||||
modificar() {
|
|
||||||
Event.$emit('sync-devoluciones', this.total, this.notas);
|
|
||||||
this.cerrar();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
mounted() {
|
|
||||||
Event.$on('modificar-devoluciones', () => {
|
|
||||||
this.visible = true;
|
|
||||||
this.total = this.$root.pedido.devoluciones_total;
|
|
||||||
this.notas = this.$root.pedido.devoluciones_notas;
|
|
||||||
Event.$emit("migas-agregar", this.miga);
|
|
||||||
});
|
|
||||||
},
|
|
||||||
}
|
|
||||||
</script>
|
|
|
@ -1,55 +0,0 @@
|
||||||
<template>
|
|
||||||
<div v-show="visible" class="block">
|
|
||||||
<div class="field">
|
|
||||||
<label class="label">Contraseña del barrio</label>
|
|
||||||
<div class="field has-addons">
|
|
||||||
<div class="control">
|
|
||||||
<input required class="input" :type="this.passwordType" name="password" placeholder="Contraseña del barrio">
|
|
||||||
</div>
|
|
||||||
<div class="control">
|
|
||||||
<a class="button is-info" @click="togglePassword">
|
|
||||||
{{ (passwordVisible ? 'Ocultar' : 'Mostrar') + ' contraseña'}}
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<p class="help">Si no la sabés, consultá a tus compañerxs.</p>
|
|
||||||
</div>
|
|
||||||
<div class="field">
|
|
||||||
<div class="control">
|
|
||||||
<input type="submit" class="button is-success" value="Ingresar"/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
export default {
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
visible: false,
|
|
||||||
gdc: this.$root.gdc,
|
|
||||||
passwordVisible: false,
|
|
||||||
passwordType: "password",
|
|
||||||
}
|
|
||||||
},
|
|
||||||
mounted() {
|
|
||||||
Event.$on('gdc-seleccionado', (gdc) => {
|
|
||||||
this.$root.gdc = gdc;
|
|
||||||
this.visible = true;
|
|
||||||
});
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
togglePassword() {
|
|
||||||
if (this.passwordVisible) this.passwordType = "password";
|
|
||||||
else this.passwordType = "text"
|
|
||||||
this.passwordVisible = !this.passwordVisible
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style>
|
|
||||||
.help {
|
|
||||||
font-size: 1rem;
|
|
||||||
}
|
|
||||||
</style>
|
|
|
@ -1,54 +0,0 @@
|
||||||
<template>
|
|
||||||
<nav class="breadcrumb is-centered has-background-danger-light is-fixed-top" aria-label="breadcrumbs" v-show="visible">
|
|
||||||
<ul class="mt-4">
|
|
||||||
<li v-for="(miga, i) in migas" :key="i" :class="{'is-active': i == migaActiva}">
|
|
||||||
<a :href="miga.href" v-text="miga.nombre"
|
|
||||||
:class="{'has-text-danger': i != migaActiva}"></a>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</nav>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
export default {
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
migas: []
|
|
||||||
}
|
|
||||||
},
|
|
||||||
computed: {
|
|
||||||
visible: function() {
|
|
||||||
return this.migas.length > 0
|
|
||||||
},
|
|
||||||
migaActiva: function() {
|
|
||||||
return this.migas.length-1
|
|
||||||
}
|
|
||||||
},
|
|
||||||
mounted() {
|
|
||||||
Event.$on('migas-setear-como-inicio', (miga) => {
|
|
||||||
this.migas = [];
|
|
||||||
this.migas.push(miga);
|
|
||||||
});
|
|
||||||
Event.$on('migas-agregar', (miga) => {
|
|
||||||
this.migas.push(miga);
|
|
||||||
});
|
|
||||||
Event.$on('migas-reset', () => {
|
|
||||||
this.migas = [];
|
|
||||||
});
|
|
||||||
Event.$on('migas-pop', () => {
|
|
||||||
this.migas.pop();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style>
|
|
||||||
nav.breadcrumb.is-fixed-top {
|
|
||||||
position: fixed;
|
|
||||||
left: 0;
|
|
||||||
right: 0;
|
|
||||||
top: 3.25rem;
|
|
||||||
height: 2.75rem;
|
|
||||||
z-index: 5;
|
|
||||||
}
|
|
||||||
</style>
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue