diff --git a/backend/app/Http/Controllers/ComprasController.php b/backend/app/Http/Controllers/ComprasController.php new file mode 100644 index 0000000..2aabf04 --- /dev/null +++ b/backend/app/Http/Controllers/ComprasController.php @@ -0,0 +1,245 @@ +validOrFail($restaurante_id); + $restaurante = Restaurante::findOrFail($restaurante_id); + + $compras = $restaurante->compras(); + + $paginate = app(PaginatorService::class)->paginate( + perPage: $request->input('per_page', 15), + page: $request->input('page', 1), + total: $compras->count(), + route: 'compras.all', + data: ['restaurante_id' => $restaurante_id] + ); + + $data = $compras->get() + ->skip($paginate['from'] - 1) + ->take($paginate['per_page']) + ->all(); + + return response()->json([ + 'pagination' => $paginate, + 'data' => $data + ]); + } + + /** + * Obtiene una compra por su id + */ + public function get(Request $request, $restaurante_id, $id) { + app(UuidService::class)->validOrFail($restaurante_id); + app(UuidService::class)->validOrFail($id); + + $restaurante = Restaurante::findOrFail($restaurante_id); + $compra = Compra::findOrFail($id); + + if($compra->restaurante != $restaurante) { + throw new ModelNotFoundException("compra", $id); + } + + return response()->json($compra); + } + + /** + * Crea una nueva compra + */ + public function create(Request $request, $restaurante_id) { + $this->validate($request, [ + 'fecha_compra' => 'required|date', + 'en_arqueo' => 'required|boolean', + 'proveedor_id' => 'required' + ]); + + app(UuidService::class)->validOrFail($restaurante_id); + app(UuidService::class)->validOrFail($request->input('proveedor_id')); + + $restaurante = Restaurante::findOrFail($restaurante_id); + $proveedor = Proveedor::findOrFail($request->input('proveedor_id')); + + if($proveedor->restaurante != $restaurante) { + throw new ModelNotFoundException("proveedor", $request->input('proveedor_id')); + } + + $compra = Compra::create([ + 'id' => Uuid::uuid4(), + 'fecha_compra' => $request->input('fecha_compra'), + 'proveedor_id' => $proveedor->id, + 'en_arqueo' => $request->input('en_arqueo'), + 'restaurante_id' => $restaurante->id + ]); + + return response()->json($compra, 201); + } + + /** + * Actualiza una compra + */ + public function update(Request $request, $restaurante_id, $id) { + $this->validate($request, [ + 'fecha_compra' => 'required|date', + 'en_arqueo' => 'required|boolean', + 'proveedor_id' => 'required' + ]); + + app(UuidService::class)->validOrFail($restaurante_id); + app(UuidService::class)->validOrFail($id); + app(UuidService::class)->validOrFail($request->input('proveedor_id')); + + $restaurante = Restaurante::findOrFail($restaurante_id); + $proveedor = Proveedor::findOrFail($request->input('proveedor_id')); + $compra = Compra::findOrFail($id); + + if($proveedor->restaurante != $restaurante) { + throw new ModelNotFoundException("proveedor", $proveedor->id); + } + + if($compra->restaurante != $restaurante) { + throw new ModelNotFoundException("compra", $compra->id); + } + + $compra->fecha_compra= $request->input('fecha_compra'); + $compra->en_arqueo = $request->input('en_arqueo'); + $compra->proveedor_id = $proveedor->id; + $compra->save(); + + return response()->json($compra); + } + + /** + * Elimina una compra + */ + public function delete(Request $request, $restaurante_id, $id) { + app(UuidService::class)->validOrFail($restaurante_id); + app(UuidService::class)->validOrFail($id); + + $restaurante = Restaurante::findOrFail($restaurante_id); + $compra = Compra::findOrFail($id); + + if($compra->restaurante != $restaurante) { + throw new ModelNotFoundException("compra", $id); + } + + $compra->ingredientes()->delete(); + $compra->facturas()->delete(); + + $compra->delete(); + + return response()->json([], 204); + } + + /** + * Obtiene los ingredientes de una compra + */ + public function getIngredientes(Request $request, $restaurante_id, $id) { + app(UuidService::class)->validOrFail($restaurante_id); + app(UuidService::class)->validOrFail($id); + + $restaurante = Restaurante::findOrFail($restaurante_id); + $compra = Compra::findOrFail($id); + + if($compra->restaurante != $restaurante) { + throw new ModelNotFoundException("compra", $id); + } + + return response()->json($compra->ingredientes); + } + + /** + * Agrega un ingrediente a una compra + */ + public function addIngrediente(Request $request, $restaurante_id, $id, $ingrediente_id) { + $this->validate($request, [ + 'unidades' => 'required|numeric', + 'monto_unitario' => 'required|numeric' + ]); + + app(UuidService::class)->validOrFail($restaurante_id); + app(UuidService::class)->validOrFail($id); + app(UuidService::class)->validOrFail($ingrediente_id); + + $restaurante = Restaurante::findOrFail($restaurante_id); + $compra = Compra::findOrFail($id); + $ingrediente = Ingrediente::findOrFail($ingrediente_id); + + if($compra->restaurante != $restaurante) { + throw new ModelNotFoundException("compra", $compra->id); + } + + if($ingrediente->restaurante != $restaurante) { + throw new ModelNotFoundException("ingrediente", $ingrediente->id); + } + + foreach($compra->ingredientes as $ci){ + if($ci->ingrediente->id == $ingrediente->id) { + throw new AlreadyExistsException("ingrediente"); + } + } + + $compraIngrediente = CompraIngrediente::create([ + 'id' => Uuid::uuid4(), + 'unidades' => $request->input('unidades'), + 'monto_unitario' => $request->input('monto_unitario'), + 'compra_id' => $compra->id, + 'ingrediente_id' => $ingrediente->id + ]); + + return response()->json($compraIngrediente, 201); + } + + /** + * Elimina un ingrediente de una compra + */ + public function deleteIngrediente(Request $request, $restaurante_id, $id, $ingrediente_id) { + app(UuidService::class)->validOrFail($restaurante_id); + app(UuidService::class)->validOrFail($id); + app(UuidService::class)->validOrFail($ingrediente_id); + + $restaurante = Restaurante::findOrFail($restaurante_id); + $compra = Compra::findOrFail($id); + $ingrediente = Ingrediente::findOrFail($ingrediente_id); + + if($compra->restaurante != $restaurante) { + throw new ModelNotFoundException("compra", $compra->id); + } + + if($ingrediente->restaurante != $restaurante) { + throw new ModelNotFoundException("ingrediente", $ingrediente->id); + } + + $toDelete = CompraIngrediente::where('compra_id', $compra->id)->where('ingrediente_id', $ingrediente->id); + + if($toDelete->count() == 0) { + throw new ModelNotFoundException("compra_ingrediente", null); + } + + $toDelete->delete(); + + return response()->json([], 204); + } +} diff --git a/backend/app/Http/Controllers/FacturasController.php b/backend/app/Http/Controllers/FacturasController.php new file mode 100644 index 0000000..b78936f --- /dev/null +++ b/backend/app/Http/Controllers/FacturasController.php @@ -0,0 +1,131 @@ +validOrFail($restaurante_id); + app(UuidService::class)->validOrFail($id); + + $restaurante = Restaurante::findOrFail($restaurante_id); + $compra = Compra::findOrFail($id); + + if($compra->restaurante != $restaurante) { + throw new ModelNotFoundException("compra", $id); + } + + if($compra->facturas()->count() == 0) { + throw new ModelNotFoundException("factura", null); + } + + return response()->json($compra->facturas()->first()); + } + + /** + * Crea una factura a una compra + */ + public function create(Request $request, $restaurante_id, $id) { + $this->validate($request, [ + 'numero' => 'required', + 'monto_bruto' => 'required|numeric', + ]); + + app(UuidService::class)->validOrFail($restaurante_id); + app(UuidService::class)->validOrFail($id); + + $restaurante = Restaurante::findOrFail($restaurante_id); + $compra = Compra::findOrFail($id); + + if($compra->restaurante != $restaurante) { + throw new ModelNotFoundException("compra", $id); + } + + if($compra->facturas()->count() > 0) { + throw new AlreadyExistsException("factura"); + } + + $factura = Factura::create([ + 'id' => Uuid::uuid4(), + 'numero' => $request->input('numero'), + 'monto_bruto' => $request->input('monto_bruto'), + 'compra_id' => $compra->id + ]); + + return response()->json($factura, 201); + } + + /** + * Modifica la factura a una compra + */ + public function update(Request $request, $restaurante_id, $id) { + $this->validate($request, [ + 'numero' => 'required', + 'monto_bruto' => 'required|numeric', + ]); + + app(UuidService::class)->validOrFail($restaurante_id); + app(UuidService::class)->validOrFail($id); + + $restaurante = Restaurante::findOrFail($restaurante_id); + $compra = Compra::findOrFail($id); + + if($compra->restaurante != $restaurante) { + throw new ModelNotFoundException("compra", $id); + } + + if($compra->facturas()->count() == 0) { + throw new ModelNotFoundException("factura", null); + } + + $factura = $compra->facturas()->first(); + $factura->numero = $request->input('numero'); + $factura->monto_bruto = $request->input('monto_bruto'); + $factura->save(); + + return response()->json($factura, 201); + } + + + /** + * Elimina la factura de una compra + */ + public function delete(Request $request, $restaurante_id, $id) { + app(UuidService::class)->validOrFail($restaurante_id); + app(UuidService::class)->validOrFail($id); + + $restaurante = Restaurante::findOrFail($restaurante_id); + $compra = Compra::findOrFail($id); + + if($compra->restaurante != $restaurante) { + throw new ModelNotFoundException("compra", $id); + } + + if($compra->facturas()->count() == 0) { + throw new ModelNotFoundException("factura", null); + } + + $factura = $compra->facturas()->first(); + $factura->delete(); + + return response()->json([], 204); + } +} diff --git a/backend/app/Models/Compra.php b/backend/app/Models/Compra.php index 575a4bf..4097bad 100644 --- a/backend/app/Models/Compra.php +++ b/backend/app/Models/Compra.php @@ -11,8 +11,17 @@ class Compra extends Model { use UuidPrimaryKey, SoftDeletes; protected $table = 'compras'; + protected $fillable = [ + 'id', 'fecha_compra', 'proveedor_id', 'en_arqueo', 'restaurante_id' + ]; - public function compraIngredientes() { + public static function findOrFail($id) { + $compra = Compra::find($id); + if(!$compra) throw new ModelNotFoundException("compra", $id); + return $compra; + } + + public function ingredientes() { return $this->hasMany(CompraIngrediente::class); } diff --git a/backend/app/Models/CompraIngrediente.php b/backend/app/Models/CompraIngrediente.php index ce2907f..e2135cc 100644 --- a/backend/app/Models/CompraIngrediente.php +++ b/backend/app/Models/CompraIngrediente.php @@ -11,6 +11,7 @@ class CompraIngrediente extends Model { use UuidPrimaryKey, SoftDeletes; protected $table = 'compra_ingredientes'; + protected $fillable = ['id', 'unidades', 'monto_unitario', 'compra_id', 'ingrediente_id']; public function ingrediente() { return $this->belongsTo(Ingrediente::class); diff --git a/backend/app/Models/Factura.php b/backend/app/Models/Factura.php index a4f7550..531b5d7 100644 --- a/backend/app/Models/Factura.php +++ b/backend/app/Models/Factura.php @@ -11,6 +11,13 @@ class Factura extends Model { use UuidPrimaryKey, SoftDeletes; protected $table = 'facturas'; + protected $fillable = ['id', 'numero', 'monto_bruto', 'compra_id']; + + public static function findOrFail($id) { + $factura = Factura::find($id); + if(!$factura) throw new ModelNotFoundException("factura", $id); + return $factura; + } public function compra() { return $this->belongsTo(Compra::class); diff --git a/backend/app/Models/Restaurante.php b/backend/app/Models/Restaurante.php index d1ca84a..2e484ca 100644 --- a/backend/app/Models/Restaurante.php +++ b/backend/app/Models/Restaurante.php @@ -2,13 +2,6 @@ namespace App\Models; -use App\Models\CanalVenta; -use App\Models\Sector; -use App\Models\ZonaProduccion; -use App\Models\Categoria; -use App\Models\Proveedor; -use App\Models\Ingrediente; -use App\Models\Producto; use App\Traits\UuidPrimaryKey; use App\Exceptions\ModelNotFoundException; use Illuminate\Database\Eloquent\Model; @@ -60,4 +53,8 @@ class Restaurante extends Model { public function productos() { return $this->hasMany(Producto::class, 'restaurante_id'); } + + public function compras() { + return $this->hasMany(Compra::class, 'restaurante_id'); + } } diff --git a/backend/routes/web.php b/backend/routes/web.php index ce37526..ecbdf75 100644 --- a/backend/routes/web.php +++ b/backend/routes/web.php @@ -72,5 +72,20 @@ $router->group(['prefix' => 'api/v1', 'middleware' => ['auth', 'log_endpoint']], $router->post( '/{restaurante_id}/productos/{producto_id}/ingredientes/{ingrediente_id}', ['as' => 'productos.receta.add_ingrediente', 'uses' => 'RecetasController@create']); $router->put( '/{restaurante_id}/productos/{producto_id}/ingredientes/{ingrediente_id}', ['as' => 'productos.receta.update_ingrediente', 'uses' => 'RecetasController@update']); $router->delete('/{restaurante_id}/productos/{producto_id}/ingredientes/{ingrediente_id}', ['as' => 'productos.receta.remove_ingrediente', 'uses' => 'RecetasController@delete']); + + $router->get( '/{restaurante_id}/compras', ['as' => 'compras.all', 'uses' => 'ComprasController@all']); + $router->get( '/{restaurante_id}/compras/{id}', ['as' => 'compras.get', 'uses' => 'ComprasController@get']); + $router->post( '/{restaurante_id}/compras', ['as' => 'compras.create', 'uses' => 'ComprasController@create']); + $router->put( '/{restaurante_id}/compras/{id}', ['as' => 'compras.update', 'uses' => 'ComprasController@update']); + $router->delete('/{restaurante_id}/compras/{id}', ['as' => 'compras.delete', 'uses' => 'ComprasController@delete']); + + $router->get( '/{restaurante_id}/compras/{id}/ingredientes', ['as' => 'compras.ingredientes.get', 'uses' => 'ComprasController@getIngredientes']); + $router->post( '/{restaurante_id}/compras/{id}/ingredientes/{ingrediente_id}', ['as' => 'compras.ingredientes.add', 'uses' => 'ComprasController@addIngrediente']); + $router->delete('/{restaurante_id}/compras/{id}/ingredientes/{ingrediente_id}', ['as' => 'compras.ingredientes.delete', 'uses' => 'ComprasController@deleteIngrediente']); + + $router->get( '/{restaurante_id}/compras/{id}/factura', ['as' => 'factura.get', 'uses' => 'FacturasController@get']); + $router->post( '/{restaurante_id}/compras/{id}/factura', ['as' => 'factura.create', 'uses' => 'FacturasController@create']); + $router->put( '/{restaurante_id}/compras/{id}/factura', ['as' => 'factura.update', 'uses' => 'FacturasController@update']); + $router->delete('/{restaurante_id}/compras/{id}/factura', ['as' => 'factura.delete', 'uses' => 'FacturasController@delete']); }); }); diff --git a/database/init/00-schema.sql b/database/init/00-schema.sql index 4f419b6..a42c740 100644 --- a/database/init/00-schema.sql +++ b/database/init/00-schema.sql @@ -183,31 +183,25 @@ create table compras create table facturas ( - id uuid primary key default gen_random_uuid(), - numero text not null, - monto_bruto bigint not null, - iva bigint not null default 0, - ila bigint not null default 0, - monto_neto bigint not null, - fecha_emision date not null, - fecha_vencimiento date not null, - compra_id uuid references compras, - created_at timestamptz not null default current_timestamp, - updated_at timestamptz not null default current_timestamp, - deleted_at timestamptz + id uuid primary key default gen_random_uuid(), + numero text not null, + monto_bruto bigint not null, + compra_id uuid references compras, + created_at timestamptz not null default current_timestamp, + updated_at timestamptz not null default current_timestamp, + deleted_at timestamptz ); create table compra_ingredientes ( - id uuid primary key default gen_random_uuid(), - unidades numeric not null, - monto_unitario_bruto bigint not null, - monto_unitario_neto bigint not null, - compra_id uuid references compras, - ingrediente_id uuid references ingredientes, - created_at timestamptz not null default current_timestamp, - updated_at timestamptz not null default current_timestamp, - deleted_at timestamptz + id uuid primary key default gen_random_uuid(), + unidades numeric not null, + monto_unitario bigint not null, + compra_id uuid references compras, + ingrediente_id uuid references ingredientes, + created_at timestamptz not null default current_timestamp, + updated_at timestamptz not null default current_timestamp, + deleted_at timestamptz ); create table sectores diff --git a/database/modifications/03-simplify-facturas.sql b/database/modifications/03-simplify-facturas.sql new file mode 100644 index 0000000..fab4bb3 --- /dev/null +++ b/database/modifications/03-simplify-facturas.sql @@ -0,0 +1,8 @@ +alter table facturas drop column iva; +alter table facturas drop column ila; +alter table facturas drop column monto_neto; +alter table facturas drop column fecha_emision; +alter table facturas drop column fecha_vencimiento; + +alter table compra_ingredientes rename column monto_unitario_bruto to monto_unitario; +alter table compra_ingredientes drop column monto_unitario_neto; \ No newline at end of file