1 | <?php |
2 | |
3 | function bdCrea(PDO $con) |
4 | { |
5 | $con->exec( |
6 | 'CREATE TABLE IF NOT EXISTS VENTA ( |
7 | VENT_ID INTEGER, |
8 | VENT_EN_CAPTURA INTEGER NOT NULL, |
9 | CONSTRAINT VENT_PK |
10 | PRIMARY KEY(VENT_ID) |
11 | )' |
12 | ); |
13 | $con->exec( |
14 | 'CREATE TABLE IF NOT EXISTS PRODUCTO ( |
15 | PROD_ID INTEGER, |
16 | PROD_NOMBRE TEXT NOT NULL, |
17 | PROD_EXISTENCIAS REAL NOT NULL, |
18 | PROD_PRECIO REAL NOT NULL, |
19 | CONSTRAINT PROD_PK |
20 | PRIMARY KEY(PROD_ID), |
21 | CONSTRAINT PROD_NOM_UNQ |
22 | UNIQUE(PROD_NOMBRE) |
23 | )' |
24 | ); |
25 | $con->exec( |
26 | 'CREATE TABLE IF NOT EXISTS DET_VENTA ( |
27 | VENT_ID INTEGER NOT NULL, |
28 | PROD_ID INTEGER NOT NULL, |
29 | DTV_CANTIDAD REAL NOT NULL, |
30 | DTV_PRECIO REAL NOT NULL, |
31 | CONSTRAINT DTV_PK |
32 | PRIMARY KEY (VENT_ID, PROD_ID), |
33 | CONSTRAINT DTV_VENT_FK |
34 | FOREIGN KEY (VENT_ID) REFERENCES VENTA(VENT_ID), |
35 | CONSTRAINT DTV_PROD_FK |
36 | FOREIGN KEY (PROD_ID) REFERENCES PRODUCTO(PROD_ID) |
37 | )' |
38 | ); |
39 | } |
40 |
1 | <?php |
2 | |
3 | require_once __DIR__ . "/../modelo/Venta.php"; |
4 | require_once __DIR__ . "/../modelo/Producto.php"; |
5 | require_once __DIR__ . "/bdCrea.php"; |
6 | require_once __DIR__ . "/productoCuenta.php"; |
7 | require_once __DIR__ . "/productoAgrega.php"; |
8 | require_once __DIR__ . "/ventaCuenta.php"; |
9 | require_once __DIR__ . "/ventaAgrega.php"; |
10 | |
11 | class Bd |
12 | { |
13 | |
14 | private static ?PDO $conexion = null; |
15 | |
16 | public static function getConexion(): PDO |
17 | { |
18 | if (self::$conexion === null) { |
19 | self::$conexion = new PDO( |
20 | // cadena de conexión |
21 | "sqlite:srvcompras.db", |
22 | // usuario |
23 | null, |
24 | // contraseña |
25 | null, |
26 | // Opciones: conexiones persistentes y lanza excepciones. |
27 | [PDO::ATTR_PERSISTENT => true, PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION] |
28 | ); |
29 | |
30 | bdCrea(self::$conexion); |
31 | if (productoCuenta() === 0) { |
32 | productoAgrega( |
33 | new Producto(nombre: "Sandwich", existencias: 50, precio: 15) |
34 | ); |
35 | productoAgrega( |
36 | new Producto(nombre: "Hot dog", existencias: 40, precio: 30) |
37 | ); |
38 | productoAgrega( |
39 | new Producto(nombre: "Hamburguesa", existencias: 30, precio: 40) |
40 | ); |
41 | } |
42 | |
43 | if (ventaCuenta() === 0) { |
44 | ventaAgrega(new Venta(enCaptura: true)); |
45 | } |
46 | } |
47 | |
48 | return self::$conexion; |
49 | } |
50 | } |
51 |
1 | <?php |
2 | |
3 | require_once __DIR__ . "/../../lib/php/ProblemDetails.php"; |
4 | require_once __DIR__ . "/../modelo/DetalleDeVenta.php"; |
5 | require_once __DIR__ . "/Bd.php"; |
6 | require_once __DIR__ . "/ventaEnCapturaBusca.php"; |
7 | require_once __DIR__ . "/productoBusca.php"; |
8 | |
9 | function detalleDeVentaAgrega(DetalleDeVenta $modelo) |
10 | { |
11 | $con = Bd::getConexion(); |
12 | $producto = productoBusca($modelo->producto->id); |
13 | if ($producto === false) { |
14 | $htmlId = htmlentities($modelo->producto->id); |
15 | throw new ProblemDetails( |
16 | status: ProblemDetails::BadRequest, |
17 | type: "/error/productonoencontrado.html", |
18 | title: "Producto no encontrado.", |
19 | detail: "No se encontró ningún producto con el id $htmlId.", |
20 | ); |
21 | } |
22 | $venta = ventaEnCapturaBusca(); |
23 | if ($venta === false) |
24 | throw new ProblemDetails( |
25 | status: ProblemDetails::BadRequest, |
26 | type: "/error/ventaencapturanoencontrada.html", |
27 | title: "Venta en captura no encontrada.", |
28 | detail: "No se encontró ninguna venta en captura.", |
29 | ); |
30 | $modelo->venta = $venta; |
31 | $modelo->precio = $producto->precio; |
32 | $modelo->producto = $producto; |
33 | $modelo->valida(); |
34 | $stmt = $con->prepare( |
35 | "INSERT INTO DET_VENTA |
36 | (VENT_ID, PROD_ID, DTV_CANTIDAD, DTV_PRECIO) |
37 | VALUES |
38 | (:ventId, :prodId, :cantidad, :precio)" |
39 | ); |
40 | $stmt->execute( |
41 | [ |
42 | ":ventId" => $venta->id, |
43 | ":prodId" => $producto->id, |
44 | ":cantidad" => $modelo->cantidad, |
45 | ":precio" => $producto->precio |
46 | ] |
47 | ); |
48 | } |
49 |
1 | <?php |
2 | |
3 | require_once __DIR__ . "/../modelo/DetalleDeVenta.php"; |
4 | require_once __DIR__ . "/Bd.php"; |
5 | require_once __DIR__ . "/ventaEnCapturaBusca.php"; |
6 | require_once __DIR__ . "/productoBusca.php"; |
7 | |
8 | function detalleDeVentaBusca(int $prodId) |
9 | { |
10 | $venta = ventaEnCapturaBusca(); |
11 | if ($venta === false) { |
12 | return false; |
13 | } |
14 | $producto = productoBusca($prodId); |
15 | if ($producto === false) { |
16 | return false; |
17 | } |
18 | $con = Bd::getConexion(); |
19 | $stmt = $con->prepare( |
20 | "SELECT |
21 | DV.PROD_ID AS prodId, |
22 | P.PROD_NOMBRE AS prodNombre, |
23 | DV.DTV_CANTIDAD AS cantidad, |
24 | DV.DTV_PRECIO AS precio |
25 | FROM DET_VENTA DV, PRODUCTO P |
26 | WHERE |
27 | DV.PROD_ID = P.PROD_ID |
28 | AND DV.VENT_ID = :ventId |
29 | AND DV.PROD_ID = :prodId" |
30 | ); |
31 | $stmt->execute([ |
32 | ":ventId" => $venta->id, |
33 | ":prodId" => $prodId |
34 | ]); |
35 | $stmt->setFetchMode(PDO::FETCH_OBJ); |
36 | $obj = $stmt->fetch(); |
37 | if ($obj === false) { |
38 | return false; |
39 | } else { |
40 | $dtv = new DetalleDeVenta(); |
41 | $dtv->venta = $venta; |
42 | $dtv->producto = $producto; |
43 | $dtv->cantidad = $obj->cantidad; |
44 | $dtv->precio = $obj->precio; |
45 | return $dtv; |
46 | } |
47 | } |
48 |
1 | <?php |
2 | |
3 | require_once __DIR__ . "/../../lib/php/recibeFetchAll.php"; |
4 | require_once __DIR__ . "/../modelo/Venta.php"; |
5 | require_once __DIR__ . "/../modelo/DetalleDeVenta.php"; |
6 | require_once __DIR__ . "/../modelo/Producto.php"; |
7 | require_once __DIR__ . "/Bd.php"; |
8 | |
9 | function detalleDeVentaConsulta(Venta $venta) |
10 | { |
11 | $con = Bd::getConexion(); |
12 | $stmt = $con->query( |
13 | "SELECT |
14 | DV.PROD_ID AS prodId, |
15 | P.PROD_NOMBRE AS prodNombre, |
16 | P.PROD_EXISTENCIAS AS prodExistencias, |
17 | P.PROD_PRECIO AS prodPrecio, |
18 | DV.DTV_CANTIDAD AS cantidad, |
19 | DV.DTV_PRECIO AS precio |
20 | FROM DET_VENTA DV, PRODUCTO P |
21 | WHERE |
22 | DV.PROD_ID = P.PROD_ID |
23 | AND DV.VENT_ID = :ventId |
24 | ORDER BY P.PROD_NOMBRE" |
25 | ); |
26 | $stmt->execute([":ventId" => $venta->id]); |
27 | $resultado = $stmt->fetchAll(PDO::FETCH_OBJ); |
28 | $objs = recibeFetchAll($resultado); |
29 | /** @var DetalleDeVenta[] */ |
30 | $detalles = []; |
31 | foreach ($objs as $obj) { |
32 | $producto = new Producto( |
33 | id: $obj->prodId, |
34 | nombre: $obj->prodNombre, |
35 | existencias: $obj->prodExistencias, |
36 | precio: $obj->prodPrecio |
37 | ); |
38 | $detalle = new DetalleDeVenta( |
39 | venta: $venta, |
40 | producto: $producto, |
41 | cantidad: $obj->cantidad, |
42 | precio: $obj->precio |
43 | ); |
44 | $detalles[] = $detalle; |
45 | } |
46 | return $detalles; |
47 | } |
48 |
1 | <?php |
2 | |
3 | require_once __DIR__ . "/Bd.php"; |
4 | require_once __DIR__ . "/ventaEnCapturaBusca.php"; |
5 | |
6 | function detalleDeVentaElimina(int $prodId) |
7 | { |
8 | $venta = ventaEnCapturaBusca(); |
9 | if ($venta !== false) { |
10 | $con = Bd::getConexion(); |
11 | $stmt = $con->prepare( |
12 | "DELETE FROM DET_VENTA |
13 | WHERE VENT_ID = :ventId |
14 | AND PROD_ID = :prodId" |
15 | ); |
16 | $stmt->execute([ |
17 | ":ventId" => $venta->id, |
18 | ":prodId" => $prodId, |
19 | ]); |
20 | } |
21 | } |
22 |
1 | <?php |
2 | |
3 | require_once __DIR__ . "/../../lib/php/ProblemDetails.php"; |
4 | require_once __DIR__ . "/../modelo/DetalleDeVenta.php"; |
5 | require_once __DIR__ . "/Bd.php"; |
6 | require_once __DIR__ . "/ventaEnCapturaBusca.php"; |
7 | require_once __DIR__ . "/productoBusca.php"; |
8 | |
9 | |
10 | function detalleDeVentaModifica(DetalleDeVenta $modelo) |
11 | { |
12 | $con = Bd::getConexion(); |
13 | $producto = productoBusca($modelo->producto->id); |
14 | if ($producto === false) { |
15 | $htmlId = htmlentities($modelo->producto->id); |
16 | throw new ProblemDetails( |
17 | status: ProblemDetails::BadRequest, |
18 | type: "/error/productonoencontrado.html", |
19 | title: "Producto no encontrado.", |
20 | detail: "No se encontró ningún producto con el id $htmlId.", |
21 | ); |
22 | } |
23 | $venta = ventaEnCapturaBusca(); |
24 | $venta = ventaEnCapturaBusca(); |
25 | if ($venta === false) |
26 | throw new ProblemDetails( |
27 | status: ProblemDetails::BadRequest, |
28 | type: "/error/ventaencapturanoencontrada.html", |
29 | title: "Venta en captura no encontrada.", |
30 | detail: "No se encontró ninguna venta en captura.", |
31 | ); |
32 | $modelo->venta = $venta; |
33 | $modelo->producto = $producto; |
34 | $modelo->precio = $producto->precio; |
35 | $modelo->valida(); |
36 | $stmt = $con->prepare( |
37 | "UPDATE DET_VENTA |
38 | SET |
39 | DTV_CANTIDAD = :cantidad, |
40 | DTV_PRECIO = :precio |
41 | WHERE |
42 | VENT_ID = :ventId |
43 | AND PROD_ID = :prodId" |
44 | ); |
45 | $stmt->execute( |
46 | [ |
47 | ":ventId" => $venta->id, |
48 | ":prodId" => $producto->id, |
49 | ":cantidad" => $modelo->cantidad, |
50 | ":precio" => $modelo->precio |
51 | ] |
52 | ); |
53 | } |
54 |
1 | <?php |
2 | |
3 | require_once __DIR__ . "/../modelo/Producto.php"; |
4 | require_once __DIR__ . "/Bd.php"; |
5 | |
6 | function productoAgrega(Producto $modelo) |
7 | { |
8 | $modelo->valida(); |
9 | $con = Bd::getConexion(); |
10 | $stmt = $con->prepare( |
11 | "INSERT INTO PRODUCTO |
12 | (PROD_NOMBRE, PROD_EXISTENCIAS, PROD_PRECIO) |
13 | VALUES |
14 | (:nombre, :existencias, :precio)" |
15 | ); |
16 | $stmt->execute([ |
17 | ":nombre" => $modelo->nombre, |
18 | ":existencias" => $modelo->existencias, |
19 | ":precio" => $modelo->precio |
20 | ]); |
21 | /* Si usas una secuencia para generar el id, |
22 | * pasa como parámetro de lastInsertId el |
23 | * nombre de dicha secuencia, debes |
24 | * ejecutarlo antes del INSERT y pasarle el |
25 | * id generado al SQL. */ |
26 | $modelo->id = $con->lastInsertId(); |
27 | } |
28 |
1 | <?php |
2 | |
3 | require_once __DIR__ . "/../modelo/Producto.php"; |
4 | require_once __DIR__ . "/Bd.php"; |
5 | |
6 | function productoBusca(int $id): false|Producto |
7 | { |
8 | $con = Bd::getConexion(); |
9 | $stmt = $con->prepare( |
10 | "SELECT |
11 | PROD_ID AS id, |
12 | PROD_NOMBRE AS nombre, |
13 | PROD_PRECIO AS precio, |
14 | PROD_EXISTENCIAS AS existencias |
15 | FROM PRODUCTO |
16 | WHERE PROD_ID = :id" |
17 | ); |
18 | $stmt->execute([":id" => $id]); |
19 | $stmt->setFetchMode( |
20 | PDO::FETCH_CLASS | PDO::FETCH_PROPS_LATE, |
21 | Producto::class |
22 | ); |
23 | return $stmt->fetch(); |
24 | } |
25 |
1 | <?php |
2 | |
3 | require_once __DIR__ . "/../../lib/php/recibeFetchAll.php"; |
4 | require_once __DIR__ . "/../modelo/Producto.php"; |
5 | require_once __DIR__ . "/Bd.php"; |
6 | |
7 | /** @return Producto[] */ |
8 | function productoConsulta(): array |
9 | { |
10 | $con = Bd::getConexion(); |
11 | $stmt = $con->query( |
12 | "SELECT |
13 | PROD_ID as id, |
14 | PROD_NOMBRE as nombre, |
15 | PROD_PRECIO as precio, |
16 | PROD_EXISTENCIAS as existencias |
17 | FROM PRODUCTO |
18 | ORDER BY PROD_NOMBRE" |
19 | ); |
20 | $resultado = $stmt->fetchAll( |
21 | PDO::FETCH_CLASS | PDO::FETCH_PROPS_LATE, |
22 | Producto::class |
23 | ); |
24 | return recibeFetchAll($resultado); |
25 | } |
26 |
1 | <?php |
2 | |
3 | require_once __DIR__ . "/Bd.php"; |
4 | |
5 | function productoCuenta(): false|int |
6 | { |
7 | $con = Bd::getConexion(); |
8 | $stmt = $con->query("SELECT COUNT(*) FROM PRODUCTO"); |
9 | return $stmt->fetchColumn(); |
10 | } |
11 |
1 | <?php |
2 | |
3 | require_once __DIR__ . "/../modelo/Venta.php"; |
4 | require_once __DIR__ . "/Bd.php"; |
5 | |
6 | function ventaAgrega(Venta $modelo) |
7 | { |
8 | $modelo->valida(); |
9 | $con = Bd::getConexion(); |
10 | $stmt = $con->prepare( |
11 | "INSERT INTO VENTA |
12 | (VENT_EN_CAPTURA) |
13 | VALUES |
14 | (:enCaptura)" |
15 | ); |
16 | $stmt->execute(([":enCaptura" => $modelo->enCaptura])); |
17 | /* Si usas una secuencia para generar el id, |
18 | * pasa como parámetro de lastInsertId el |
19 | * nombre de dicha secuencia, debes |
20 | * ejecutarlo antes del INSERT y pasarle el |
21 | * id generado al SQL. */ |
22 | $modelo->id = $con->lastInsertId(); |
23 | } |
24 |
1 | <?php |
2 | |
3 | require_once __DIR__ . "/Bd.php"; |
4 | |
5 | function ventaCuenta(): false|int |
6 | { |
7 | $con = Bd::getConexion(); |
8 | $stmt = $con->query("SELECT COUNT(*) FROM VENTA"); |
9 | return $stmt->fetchColumn(); |
10 | } |
11 |
1 | <?php |
2 | |
3 | require_once __DIR__ . "/../modelo/Venta.php"; |
4 | require_once __DIR__ . "/Bd.php"; |
5 | require_once __DIR__ . "/detalleDeVentaConsulta.php"; |
6 | |
7 | function ventaEnCapturaBusca() |
8 | { |
9 | $con = Bd::getConexion(); |
10 | $stmt = $con->query( |
11 | "SELECT VENT_ID as id |
12 | FROM VENTA |
13 | WHERE VENT_EN_CAPTURA = 1" |
14 | ); |
15 | $stmt->setFetchMode(PDO::FETCH_OBJ); |
16 | $obj = $stmt->fetch(); |
17 | if ($obj === false) { |
18 | return false; |
19 | } else { |
20 | $venta = new Venta(id: $obj->id, enCaptura: true); |
21 | $venta->detalles = detalleDeVentaConsulta($venta); |
22 | return $venta; |
23 | } |
24 | } |
25 |
1 | <?php |
2 | |
3 | require_once __DIR__ . "/../modelo/Venta.php"; |
4 | require_once __DIR__ . "/Bd.php"; |
5 | require_once __DIR__ . "/ventaEnCapturaBusca.php"; |
6 | require_once __DIR__ . "/ventaAgrega.php"; |
7 | |
8 | function ventaEnCapturaProcesa() |
9 | { |
10 | $con = Bd::getConexion(); |
11 | $con->beginTransaction(); |
12 | $modelo = ventaEnCapturaBusca(); |
13 | if ($modelo === false) |
14 | throw new Exception("Venta no encontrada."); |
15 | $modelo->valida(); |
16 | $detalles = $modelo->detalles; |
17 | $stmt = $con->prepare( |
18 | "UPDATE PRODUCTO |
19 | SET PROD_EXISTENCIAS = :existencias |
20 | WHERE PROD_ID = :prodId" |
21 | ); |
22 | foreach ($detalles as $dtv) { |
23 | $producto = $dtv->producto; |
24 | $stmt->execute(([ |
25 | ":prodId" => $producto->id, |
26 | ":existencias" => $producto->existencias - $dtv->cantidad |
27 | ])); |
28 | } |
29 | $stmt = $con->prepare( |
30 | "UPDATE VENTA |
31 | SET VENT_EN_CAPTURA = 0 |
32 | WHERE VENT_ID = :id" |
33 | ); |
34 | $stmt->execute([":id" => $modelo->id]); |
35 | ventaAgrega(new Venta(enCaptura: true)); |
36 | $con->commit(); |
37 | } |
38 |