funcion: notas de producto #36
|
@ -233,10 +233,36 @@ class GrupoDeCompra extends Model
|
|||
|
||||
// Guardar en un archivo .csv
|
||||
try {
|
||||
$writer = Writer::createFromPath(resource_path('csv/exports/total-pedidos.csv'), 'w');
|
||||
$writer->insertAll($planilla);
|
||||
$writer = Writer::createFromPath(resource_path('csv/exports/total-pedidos.csv'), 'w');
|
||||
$writer->insertAll($planilla);
|
||||
} catch (CannotInsertRecord $e) {
|
||||
var_export($e->getRecords());
|
||||
var_export($e->getRecords());
|
||||
}
|
||||
}
|
||||
|
||||
public static function exportarProductosConNotasEnCSV() {
|
||||
$gdcs = GrupoDeCompra::all();
|
||||
foreach ($gdcs as $i => $gdc) {
|
||||
$productos_en_pedido = DB::table('pedidos_aprobados')->where('grupo_de_compra_id', $gdc->id)->get()->keyBy('producto_id');
|
||||
$pedidos = $gdc->pedidosAprobados();
|
||||
foreach ($productos_en_pedido as $id => $producto_pedido) {
|
||||
foreach ($pedidos as $pedido) {
|
||||
$producto = $pedido->productos()->find($id);
|
||||
if ($producto != null && $producto->requiere_notas) {
|
||||
$planilla[$i+1][0] = $gdc->nombre;
|
||||
$planilla[$i+1][1] = $producto->nombre;
|
||||
$planilla[$i+1][2] = $producto->pivot->cantidad;
|
||||
$planilla[$i+1][3] = $producto->pivot->notas;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// Guardar en un archivo .csv
|
||||
try {
|
||||
$writer = Writer::createFromPath(resource_path('csv/exports/pedidos-notas.csv'), 'w');
|
||||
$writer->insertAll($planilla);
|
||||
} catch (CannotInsertRecord $e) {
|
||||
var_export($e->getRecords());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -79,6 +79,7 @@ class SubpedidoController extends Controller
|
|||
|
||||
$valid = request()->validate([
|
||||
'cantidad' => 'required|min:0',
|
||||
'notas' => 'nullable',
|
||||
'producto_id' => [
|
||||
'required',
|
||||
Rule::in(Producto::all()->pluck('id')),
|
||||
|
@ -86,7 +87,11 @@ class SubpedidoController extends Controller
|
|||
]);
|
||||
|
||||
$producto = Producto::find($valid['producto_id']);
|
||||
$subpedido->syncProducto($producto, $valid['cantidad']);
|
||||
$notas = $valid['notas'];
|
||||
if ($notas == null) {
|
||||
$notas = "";
|
||||
}
|
||||
$subpedido->syncProducto($producto, $valid['cantidad'], $notas);
|
||||
return new SubpedidoResource($subpedido);
|
||||
}
|
||||
|
||||
|
|
|
@ -15,6 +15,12 @@ class ComprasController
|
|||
$file = resource_path('csv/exports/total-pedidos.csv');
|
||||
return response()->download($file);
|
||||
}
|
||||
|
||||
public function descargarNotas() {
|
||||
GrupoDeCompra::exportarProductosConNotasEnCSV();
|
||||
$file = resource_path('csv/exports/pedidos-notas.csv');
|
||||
return response()->download($file);
|
||||
}
|
||||
|
||||
public function show()
|
||||
{
|
||||
|
|
|
@ -25,7 +25,8 @@ class ProductoResource extends JsonResource
|
|||
'imagen' => optional($this->poster)->url(),
|
||||
'descripcion' => $this->descripcion,
|
||||
'apto_veganxs' => $this->apto_veganxs,
|
||||
'apto_celiacxs' => $this->apto_celiacxs
|
||||
'apto_celiacxs' => $this->apto_celiacxs,
|
||||
'requiere_notas' => $this->requiere_notas,
|
||||
];
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,7 +15,7 @@ class Producto extends Model
|
|||
|
||||
public function subpedidos()
|
||||
{
|
||||
return $this->belongsToMany('App\Subpedido','productos_subpedidos')->withPivot(["cantidad"]);
|
||||
return $this->belongsToMany('App\Subpedido','productos_subpedidos')->withPivot(["cantidad", "notas"]);
|
||||
}
|
||||
|
||||
public function proveedor()
|
||||
|
|
|
@ -15,7 +15,7 @@ class Subpedido extends Model
|
|||
|
||||
public function productos()
|
||||
{
|
||||
return $this->belongsToMany('App\Producto')->withPivot(["cantidad","total"]);
|
||||
return $this->belongsToMany('App\Producto')->withPivot(["cantidad","total", "notas"]);
|
||||
}
|
||||
|
||||
//Bonos del MPS, Sororo, etc. NO devuelve bonos de transporte
|
||||
|
@ -84,13 +84,14 @@ class Subpedido extends Model
|
|||
}
|
||||
|
||||
//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) {
|
||||
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
|
||||
'total' => $cantidad * $producto->precio,
|
||||
'notas' => $notas,
|
||||
]
|
||||
]);
|
||||
} else {
|
||||
|
|
|
@ -0,0 +1,32 @@
|
|||
<?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');
|
||||
});
|
||||
}
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
<?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');
|
||||
});
|
||||
}
|
||||
}
|
|
@ -61,7 +61,8 @@ class CanastaSeeder extends Seeder
|
|||
'nombre' => trim(str_replace('*', ' ',$registro['Producto'])),
|
||||
'precio' => $registro['Precio'],
|
||||
'proveedor_id' => $this->obtenerProveedor($registro['Producto']),
|
||||
'bono' => $registro[$this::FILA_HEADER] == "B"
|
||||
'bono' => $registro[$this::FILA_HEADER] == "B",
|
||||
'requiere_notas'=> $registro[$this::FILA_HEADER] =="PTC",
|
||||
];
|
||||
}
|
||||
|
||||
|
|
|
@ -13,5 +13,6 @@ class DatabaseSeeder extends Seeder
|
|||
public function run()
|
||||
{
|
||||
$this->call(CanastaSeeder::class);
|
||||
$this->call(GrupoDeCompraSeeder::class);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -31,14 +31,14 @@ class GrupoDeCompraSeeder extends Seeder
|
|||
|
||||
$usersToInsert[] = [
|
||||
'name' => $registro['barrio'],
|
||||
'password' => Hash::make($registro['barrio']),
|
||||
'password' => Hash::make("asd"),
|
||||
"is_admin" => 0,
|
||||
'grupo_de_compra_id' => $key
|
||||
];
|
||||
|
||||
$usersToInsert[] = [
|
||||
'name' => $registro['barrio'] . "_admin",
|
||||
'password' => Hash::make($registro['barrio'] . "admin"),
|
||||
'password' => Hash::make("asd"),
|
||||
"is_admin" => 1,
|
||||
'grupo_de_compra_id' => $key
|
||||
];
|
||||
|
|
|
@ -70,6 +70,10 @@ const app = new Vue({
|
|||
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`)
|
||||
|
@ -99,14 +103,15 @@ const app = new Vue({
|
|||
}
|
||||
})
|
||||
})
|
||||
Event.$on('sync-subpedido', (cantidad, id) => {
|
||||
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
|
||||
producto_id: id,
|
||||
notas: notas,
|
||||
}).then((response) => {
|
||||
this.pedido = response.data.data
|
||||
this.$toast('Pedido actualizado exitosamente')
|
||||
|
|
|
@ -11,6 +11,16 @@
|
|||
</a>
|
||||
</p>
|
||||
</div>
|
||||
<div class="field">
|
||||
<p class="control">
|
||||
<a href="/compras/pedidos/notas" class="button">
|
||||
<span class="icon is-small">
|
||||
<i class="fas fa-sticky-note"></i>
|
||||
</span>
|
||||
<span>Descargar planilla de notas</span>
|
||||
</a>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
|
|
@ -1,28 +1,44 @@
|
|||
<template>
|
||||
<div class="field has-addons contador">
|
||||
<div class="control">
|
||||
<button class="button is-small" @click.capture="decrementar();">
|
||||
<i class="fa fa-solid fa-minus"></i>
|
||||
<div>
|
||||
<div class="field has-addons contador">
|
||||
<div class="control">
|
||||
<button class="button is-small" @click.capture="decrementar();">
|
||||
<i class="fa fa-solid fa-minus"></i>
|
||||
</button>
|
||||
</div>
|
||||
<div class="control">
|
||||
<input id="cantidad" v-model="cantidad" class="input is-small" type="number" style="text-align: center">
|
||||
</div>
|
||||
<div class="control" @click="incrementar();">
|
||||
<button class="button is-small">
|
||||
<i class="fa fa-solid fa-plus"></i>
|
||||
</button>
|
||||
</div>
|
||||
<button :disabled="disableConfirm()" class="button is-small is-success ml-1" @click="confirmar()">
|
||||
<span class="icon">
|
||||
<i class="fas fa-check"></i>
|
||||
</span>
|
||||
</button>
|
||||
<button :disabled="!puedeBorrar()" class="button is-small is-danger ml-1" @click="borrar()">
|
||||
<span class="icon">
|
||||
<i class="fas fa-trash-alt"></i>
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="control">
|
||||
<input id="cantidad" v-model="cantidad" class="input is-small" type="number" style="text-align: center">
|
||||
</div>
|
||||
<div class="control" @click="incrementar();">
|
||||
<button class="button is-small">
|
||||
<i class="fa fa-solid fa-plus"></i>
|
||||
</button>
|
||||
</div>
|
||||
<button :disabled="!hayCambios()" class="button is-small is-success ml-1" @click="confirmar()">
|
||||
<span class="icon">
|
||||
<i class="fas fa-check"></i>
|
||||
<div v-if="producto.requiere_notas" v-bind:class="{'has-icons-right': notas_warning_visible}" class="control is-full-width has-icons-left">
|
||||
<span class="icon is-small is-left">
|
||||
<i class="fas fa-sticky-note"></i>
|
||||
</span>
|
||||
</button>
|
||||
<button :disabled="!puedeBorrar()" class="button is-small is-danger ml-1" @click="borrar()">
|
||||
<span class="icon">
|
||||
<i class="fas fa-trash-alt"></i>
|
||||
<input v-model="notas" v-bind:class="{'is-danger': notas_warning_visible}" id="notas" class="input" type="text" placeholder="Talle o color" />
|
||||
<span v-if="notas_warning_visible" class="icon is-small is-right">
|
||||
<i class="fas fa-exclamation-triangle"></i>
|
||||
</span>
|
||||
</button>
|
||||
<article v-if="notas_warning_visible" class="message is-danger is-small">
|
||||
<div class="message-body">
|
||||
No se puede dejar este campo vacío
|
||||
</div>
|
||||
</article>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
@ -33,21 +49,24 @@
|
|||
},
|
||||
data() {
|
||||
return {
|
||||
cantidad: this.producto.cantidad,
|
||||
enChismosa: this.producto.cantidad,
|
||||
cantidad: this.cantidadEnChismosa(),
|
||||
notas: this.notasEnChismosa(),
|
||||
notas_warning_visible: false,
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
if (this.producto.pivot !== undefined) {
|
||||
this.cantidad = this.producto.pivot.cantidad;
|
||||
this.enChismosa = this.cantidad;
|
||||
}
|
||||
Event.$on('sync-subpedido', (cantidad,productoId) => {
|
||||
if (this.producto.id === productoId)
|
||||
this.sincronizar(cantidad);
|
||||
Event.$on('sync-subpedido', (cantidad, productoId, notas) => {
|
||||
if (this.producto.id === productoId)
|
||||
this.sincronizar(cantidad, notas);
|
||||
});
|
||||
},
|
||||
methods: {
|
||||
notasEnChismosa() {
|
||||
return this.producto.pivot !== undefined ? this.producto.pivot.notas : "";
|
||||
},
|
||||
cantidadEnChismosa() {
|
||||
return this.producto.pivot !== undefined ? this.producto.pivot.cantidad : 0;
|
||||
},
|
||||
decrementar() {
|
||||
this.cantidad -= 1;
|
||||
},
|
||||
|
@ -55,26 +74,39 @@
|
|||
this.cantidad += 1;
|
||||
},
|
||||
confirmar() {
|
||||
Event.$emit('sync-subpedido', this.cantidad, this.producto.id);
|
||||
if (this.warningNotas()) {
|
||||
this.notas_warning_visible = true;
|
||||
return;
|
||||
}
|
||||
console.log("Emit sync " + this.cantidad + " " + this.notas);
|
||||
Event.$emit('sync-subpedido', this.cantidad, this.producto.id, this.notas);
|
||||
},
|
||||
borrar() {
|
||||
this.cantidad = 0;
|
||||
this.confirmar();
|
||||
},
|
||||
sincronizar(cantidad) {
|
||||
sincronizar(cantidad, notas) {
|
||||
this.notas_warning_visible = false;
|
||||
this.notas = notas;
|
||||
this.cantidad = cantidad;
|
||||
if (this.producto.pivot != null) {
|
||||
if (this.producto.pivot !== undefined) {
|
||||
this.producto.pivot.cantidad = cantidad;
|
||||
} else {
|
||||
this.producto.cantidad = cantidad;
|
||||
this.producto.pivot.notas = notas;
|
||||
}
|
||||
this.enChismosa = cantidad;
|
||||
},
|
||||
hayCambios() {
|
||||
return this.cantidad != this.enChismosa;
|
||||
if (this.cantidad != this.cantidadEnChismosa()) return true;
|
||||
|
||||
return this.cantidad > 0 && this.notas != this.notasEnChismosa();
|
||||
},
|
||||
puedeBorrar() {
|
||||
return this.enChismosa > 0;
|
||||
return this.cantidadEnChismosa() > 0;
|
||||
},
|
||||
warningNotas() {
|
||||
return this.producto.requiere_notas && this.cantidad > 0 && !this.notas;
|
||||
},
|
||||
disableConfirm() {
|
||||
return !this.hayCambios();
|
||||
},
|
||||
}
|
||||
}
|
||||
|
@ -97,4 +129,12 @@
|
|||
.contador {
|
||||
min-width: 178px;
|
||||
}
|
||||
|
||||
.is-danger {
|
||||
background-color: #fca697;
|
||||
}
|
||||
.is-danger::placeholder {
|
||||
color: #fff;
|
||||
opacity: 1; /* Firefox */
|
||||
}
|
||||
</style>
|
|
@ -8,12 +8,13 @@ export default {
|
|||
return {
|
||||
cantidad: this.producto.cantidad,
|
||||
enChismosa: this.producto.cantidad,
|
||||
notas: this.producto.notas,
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
Event.$on('sync-subpedido', (cantidad,productoId) => {
|
||||
Event.$on('sync-subpedido', (cantidad, productoId, notas) => {
|
||||
if (this.producto.id === productoId)
|
||||
this.sincronizar(cantidad);
|
||||
this.sincronizar(cantidad, notas);
|
||||
});
|
||||
},
|
||||
methods: {
|
||||
|
@ -24,19 +25,21 @@ export default {
|
|||
this.cantidad += 1;
|
||||
},
|
||||
confirmar() {
|
||||
Event.$emit('sync-subpedido', this.cantidad, this.producto.id);
|
||||
Event.$emit('sync-subpedido', this.cantidad, this.producto.id, this.notas);
|
||||
},
|
||||
borrar() {
|
||||
this.cantidad = 0;
|
||||
this.confirmar();
|
||||
},
|
||||
sincronizar(cantidad) {
|
||||
sincronizar(cantidad, notas) {
|
||||
this.cantidad = cantidad;
|
||||
this.producto.cantidad = cantidad;
|
||||
this.enChismosa = cantidad;
|
||||
this.notas = notas;
|
||||
this.producto.notas = notas;
|
||||
},
|
||||
hayCambios() {
|
||||
return this.cantidad != this.enChismosa;
|
||||
return this.cantidad != this.enChismosa || this.notas != this.producto.notas;
|
||||
},
|
||||
puedeBorrar() {
|
||||
return this.enChismosa > 0;
|
||||
|
|
|
@ -34,7 +34,11 @@ export default {
|
|||
params: this.params(filtro,valor)
|
||||
}).then(response => {
|
||||
this.productos = response.data.data;
|
||||
this.productos.forEach(p => p.cantidad = this.$root.cantidad(p))
|
||||
this.productos.forEach(p => {
|
||||
p.pivot = {};
|
||||
p.pivot.cantidad = this.$root.cantidad(p);
|
||||
p.pivot.notas = this.$root.notas(p);
|
||||
});
|
||||
});
|
||||
this.visible = true;
|
||||
Event.$emit("migas-agregar",this.miga);
|
||||
|
|
|
@ -27,9 +27,13 @@
|
|||
|
||||
@foreach($subpedido->productos as $producto)
|
||||
@if(!$producto->bono)
|
||||
|
||||
<tr>
|
||||
<td>
|
||||
{{ $producto->nombre }}
|
||||
@if($producto->pivot->notas)
|
||||
<br /><b>Talle/Color:</b> {{ $producto->pivot->notas }}
|
||||
@endif
|
||||
</td>
|
||||
<td style="text-align: center">
|
||||
{{ $producto->pivot->cantidad }}
|
||||
|
|
|
@ -81,4 +81,5 @@ Route::get('/compras', 'ComprasController@show')->name('compras_login.show');
|
|||
Route::middleware(['compras'])->group( function() {
|
||||
Route::get('/compras/pedidos', 'ComprasController@indexPedidos')->name('compras.pedidos');
|
||||
Route::get('/compras/pedidos/descargar', 'ComprasController@descargarPedidos')->name('compras.pedidos.descargar');
|
||||
Route::get('/compras/pedidos/notas', 'ComprasController@descargarNotas')->name('compras.pedidos.descargar');
|
||||
});
|
||||
|
|
Loading…
Reference in New Issue