diff --git a/api/db/transaction.go b/api/db/transaction.go
index 2ef9a38ddfd128ad1d6fc5336cce44580a89af63..e888c499d57cdd0ceb1c3283e0b233a54337d537 100644
--- a/api/db/transaction.go
+++ b/api/db/transaction.go
@@ -12,6 +12,10 @@ import (
 	"gorm.io/gorm/clause"
 )
 
+const (
+	dateLayout = "2006-01-02"
+)
+
 type Transaction struct {
 	gorm.Model
 	MemberNum int       `json:"-" gorm:"column:member"`
@@ -37,7 +41,7 @@ type Topup struct {
 }
 
 type Purchase struct {
-	gorm.Model    `json:"-"`
+	gorm.Model
 	TransactionID uint    `json:"-" gorm:"column:transaction"`
 	ProductCode   int     `json:"code" gorm:"column:product"`
 	Product       Product `json:"product" gorm:"foreignKey:ProductCode;references:Code"`
@@ -45,9 +49,11 @@ type Purchase struct {
 	Amount        int     `json:"amount"`
 }
 
-func (d *DB) ListTransactions(query map[string][]string) (transactions []Transaction, err error) {
-	const dateLayout = "2006-01-02"
+func (d *DB) ListTransactions(num int, query map[string][]string) (transactions []Transaction, err error) {
 	tx := d.transactionQuery()
+	if num != 0 {
+		tx = tx.Where("member = ?", num)
+	}
 	for k, v := range query {
 		switch k {
 		case "start-date":
@@ -66,6 +72,9 @@ func (d *DB) ListTransactions(query map[string][]string) (transactions []Transac
 			}
 			tx = tx.Where("date <= ?", date)
 		case "member":
+			if num != 0 {
+				continue
+			}
 			tx = tx.Where("member in ?", v)
 		case "proxy":
 			tx = tx.Where("proxy in ?", v)
@@ -91,14 +100,7 @@ func (d *DB) ListTransactions(query map[string][]string) (transactions []Transac
 			log.Printf("Unexpected transaction query: %s %v", k, v)
 		}
 	}
-	err = tx.Order("date desc").
-		Find(&transactions).Error
-	return
-}
-
-func (d *DB) TransactionByMember(num int) (transactions []Transaction, err error) {
-	err = d.transactionQuery().
-		Where("member = ?", num).
+	err = tx.Group("transactions.id").
 		Order("date desc").
 		Find(&transactions).Error
 	return
diff --git a/api/transaction.go b/api/transaction.go
index c70c31ce475392c2257f2cfc3a601f9d23d1edc4..5af75f7366b2394176d94a2ab71cd6dd961070a3 100644
--- a/api/transaction.go
+++ b/api/transaction.go
@@ -12,26 +12,7 @@ import (
 )
 
 func (a *api) ListTransactions(w http.ResponseWriter, req *http.Request) {
-	err := req.ParseForm()
-	if err != nil {
-		log.Printf("Can't parse the query: %v", err)
-		w.WriteHeader(http.StatusInternalServerError)
-		return
-	}
-
-	transactions, err := a.db.ListTransactions(req.Form)
-	if err != nil {
-		log.Printf("Can't list transactions: %v", err)
-		w.WriteHeader(http.StatusInternalServerError)
-		return
-	}
-	w.Header().Set("Content-Type", "application/json")
-	w.WriteHeader(http.StatusOK)
-	err = json.NewEncoder(w).Encode(transactions)
-	if err != nil {
-		log.Printf("Can't encode transactions: %v", err)
-		w.WriteHeader(http.StatusInternalServerError)
-	}
+	a.getTransactionsByMember(0, w, req)
 }
 
 func (a *api) GetTransaction(num int, role string, w http.ResponseWriter, req *http.Request) {
@@ -70,7 +51,14 @@ func (a *api) GetMemberTransactions(w http.ResponseWriter, req *http.Request) {
 }
 
 func (a *api) getTransactionsByMember(num int, w http.ResponseWriter, req *http.Request) {
-	transactions, err := a.db.TransactionByMember(num)
+	err := req.ParseForm()
+	if err != nil {
+		log.Printf("Can't parse the query: %v", err)
+		w.WriteHeader(http.StatusInternalServerError)
+		return
+	}
+
+	transactions, err := a.db.ListTransactions(num, req.Form)
 	if err != nil {
 		log.Printf("Can't list transactions: %v", err)
 		w.WriteHeader(http.StatusInternalServerError)
diff --git a/src/Head.js b/src/Head.js
index 9934e1fced3a060ba2615d6f9085baa35994dc8e..a90058afe40269f25bcf55ce0c9cc78987fd519b 100644
--- a/src/Head.js
+++ b/src/Head.js
@@ -32,29 +32,29 @@ function Head(props) {
     );
   }
 
-  let productNav = (
-    <LinkContainer to="/products">
-      <Nav.Link>Productos</Nav.Link>
-    </LinkContainer>
+  const productNav = (
+    <NavDropdown title="Almacen" id="almacen">
+      <LinkContainer to="/products">
+        <NavDropdown.Item>Productos</NavDropdown.Item>
+      </LinkContainer>
+      <LinkContainer to="/purchases">
+        <NavDropdown.Item>Compras</NavDropdown.Item>
+      </LinkContainer>
+      {auth.role === "admin" && (
+        <div>
+          <LinkContainer to="/inventary">
+            <NavDropdown.Item>Entradas Almacén</NavDropdown.Item>
+          </LinkContainer>
+          <LinkContainer to="/supplier/add">
+            <NavDropdown.Item>Alta Proveedores</NavDropdown.Item>
+          </LinkContainer>
+          <LinkContainer to="/product/add">
+            <NavDropdown.Item>Alta Codigos</NavDropdown.Item>
+          </LinkContainer>
+        </div>
+      )}
+    </NavDropdown>
   );
-  if (auth.role === "admin") {
-    productNav = (
-      <NavDropdown title="Almacen" id="admin">
-        <LinkContainer to="/products">
-          <NavDropdown.Item>Productos</NavDropdown.Item>
-        </LinkContainer>
-        <LinkContainer to="/inventary">
-          <NavDropdown.Item>Entradas Almacén</NavDropdown.Item>
-        </LinkContainer>
-        <LinkContainer to="/supplier/add">
-          <NavDropdown.Item>Alta Proveedores</NavDropdown.Item>
-        </LinkContainer>
-        <LinkContainer to="/product/add">
-          <NavDropdown.Item>Alta Codigos</NavDropdown.Item>
-        </LinkContainer>
-      </NavDropdown>
-    );
-  }
 
   let orderNav = (
     <LinkContainer to="/orders">
diff --git a/src/Panel.js b/src/Panel.js
index 9a7e68fbd301c571b6f688d6da417146ba02e707..a97ac13bac5e4efe4ca704825aa8d361e1cca1aa 100644
--- a/src/Panel.js
+++ b/src/Panel.js
@@ -12,6 +12,7 @@ import ShowInventary from "./inventary/ShowInventary";
 import CreateSupplier from "./inventary/CreateSupplier";
 import Dashboard from "./Dashboard";
 import OwnPassword from "./OwnPassword";
+import PurchaseList from "./purchase/PurchaseList";
 import Purchase from "./purchase/Purchase";
 import Topup from "./Topup";
 import ShowTransaction from "./transaction/ShowTransaction";
@@ -82,6 +83,9 @@ function LogedPanel(props) {
             <Route path="/purchase">
               <Purchase />
             </Route>
+            <Route path="/purchases">
+              <PurchaseList />
+            </Route>
             <Route path="/topup/:num">
               <Topup />
             </Route>
diff --git a/src/product/ProductPicker.js b/src/product/ProductPicker.js
index ed723c9647cc6dc060de55e16157fa5b4cd2743b..79d815224941d87b489d99a81f980a5dcaac23bd 100644
--- a/src/product/ProductPicker.js
+++ b/src/product/ProductPicker.js
@@ -75,14 +75,9 @@ class ProductPicker extends React.Component {
 
   render() {
     const rows = this.props.picks.map((p, i) => {
-      return (
-        <Form.Group key={p.code} as={Row}>
-          <Col>
-            <p>{p.code}</p>
-          </Col>
-          <Col xs={4}>
-            <p>{p.name}</p>
-          </Col>
+      let price;
+      if (!this.props.noPrice) {
+        price = (
           <Col>
             {this.props.price ? (
               <PriceEditor
@@ -93,6 +88,17 @@ class ProductPicker extends React.Component {
               printMoney(p.price) + "€"
             )}
           </Col>
+        );
+      }
+      return (
+        <Form.Group key={p.code} as={Row}>
+          <Col>
+            <p>{p.code}</p>
+          </Col>
+          <Col xs={4}>
+            <p>{p.name}</p>
+          </Col>
+          {price}
           {(this.props.amount || this.props.stock) && (
             <Col>
               <Form.Control
@@ -123,9 +129,11 @@ class ProductPicker extends React.Component {
           <Col xs={4}>
             <h6>Nombre</h6>
           </Col>
-          <Col>
-            <h6>Precio</h6>
-          </Col>
+          {!this.props.noPrice && (
+            <Col>
+              <h6>Precio</h6>
+            </Col>
+          )}
           {(this.props.amount || this.props.stock) && (
             <Col>
               <h6>Cantidad</h6>
@@ -152,7 +160,7 @@ class ProductPicker extends React.Component {
               selected={[]}
             />
           </Col>
-          <Col xs={false} sm></Col>
+          {!this.props.noPrice && <Col xs={false} sm></Col>}
           {(this.props.amount || this.props.stock) && <Col xs={false} sm></Col>}
           <Col xs={false} sm={1}></Col>
         </Form.Group>
diff --git a/src/purchase/PurchaseList.js b/src/purchase/PurchaseList.js
new file mode 100644
index 0000000000000000000000000000000000000000..259f8d33d4bfc67b12f1a10a021dad98bac6eed3
--- /dev/null
+++ b/src/purchase/PurchaseList.js
@@ -0,0 +1,147 @@
+import React, { useState, useContext } from "react";
+import { Table, Form, Row, Col, Button } from "react-bootstrap";
+import { LinkContainer } from "react-router-bootstrap";
+import ProductPicker from "../product/ProductPicker";
+import MemberPicker from "../member/MemberPicker";
+import AuthContext from "../AuthContext";
+import Fetcher from "../Fetcher";
+import { date2string, daysAfterNow, printDate } from "../util";
+
+function PurchaseList() {
+  const auth = useContext(AuthContext);
+  const [purchases, setPurchases] = useState([]);
+  const [startDate, setStartDate] = useState(date2string(daysAfterNow(-30)));
+  const [endDate, setEndDate] = useState(date2string(new Date()));
+  const [members, setMembers] = useState([]);
+  const [products, setProducts] = useState([]);
+
+  const setTransactions = (transactions) => {
+    const pur = transactions
+      .map((t) => {
+        let purchases = t.purchase;
+        if (products.length !== 0) {
+          purchases = purchases.filter(
+            (p) => products.find((prod) => p.code === prod.code) !== undefined
+          );
+        }
+        return purchases.map((p) => {
+          return {
+            ID: p.ID,
+            date: t.date,
+            product: p.product.name,
+            code: p.code,
+            amount: p.amount,
+            member: t.member.name,
+            num: t.member.num,
+            transaction: t.ID,
+          };
+        });
+      })
+      .flat();
+    setPurchases(pur);
+  };
+
+  const admin = auth.role === "admin";
+
+  let query = "type=purchase&start-date=" + startDate + "&end-date=" + endDate;
+  query += members.map((m) => "&member=" + m.num).join("");
+  query += products.map((p) => "&product=" + p.code).join("");
+
+  const entries = purchases.map((p) => {
+    return (
+      <LinkContainer to={"/transaction/" + p.transaction} key={p.ID}>
+        <tr>
+          <td>{printDate(p.date)}</td>
+          <td>{p.product}</td>
+          <td>{p.amount}</td>
+          {admin && <td>{p.member}</td>}
+        </tr>
+      </LinkContainer>
+    );
+  });
+
+  const setMember = (m) => {
+    let newMembers = [...members];
+    newMembers.push(m);
+    setMembers(newMembers);
+  };
+  const delMember = (index) => {
+    let newMembers = [...members];
+    newMembers.splice(index, 1);
+    setMembers(newMembers);
+  };
+  let memberPicker;
+  if (admin) {
+    const rows = members.map((member, i) => (
+      <Row key={member.num}>
+        <Col>
+          <p>{member.name}</p>
+        </Col>
+        <Col xs={1}>
+          <Button variant="danger" onClick={() => delMember(i)}>
+            -
+          </Button>
+        </Col>
+      </Row>
+    ));
+    memberPicker = (
+      <Col xs={12} sm={6}>
+        {rows}
+        <MemberPicker onChange={setMember} />
+      </Col>
+    );
+  }
+
+  return (
+    <div>
+      <Form>
+        <Row>
+          <Form.Group as={Col}>
+            <Form.Label>Desde:</Form.Label>
+            <Form.Control
+              type="date"
+              value={startDate}
+              onChange={(e) => setStartDate(e.target.value)}
+              max={endDate}
+            />
+          </Form.Group>
+          <Form.Group as={Col}>
+            <Form.Label>Hasta:</Form.Label>
+            <Form.Control
+              type="date"
+              value={endDate}
+              onChange={(e) => setEndDate(e.target.value)}
+              min={startDate}
+              max={Date.now()}
+            />
+          </Form.Group>
+        </Row>
+        <Row>
+          <Col>
+            <ProductPicker picks={products} setPicks={setProducts} noPrice />
+          </Col>
+          {memberPicker}
+        </Row>
+      </Form>
+      <br />
+      <Fetcher
+        url={(admin ? "/api/transaction?" : "/api/transaction/mine?") + query}
+        onFetch={setTransactions}
+      >
+        <Table className="text-center" responsive>
+          <thead>
+            <tr>
+              <th>Fecha</th>
+              <th>Producto</th>
+              <th>Cantidad</th>
+              {admin && <th>Socia</th>}
+            </tr>
+          </thead>
+          <tbody>{entries}</tbody>
+        </Table>
+      </Fetcher>
+    </div>
+  );
+}
+
+export default PurchaseList;
diff --git a/src/transaction/TransactionList.js b/src/transaction/TransactionList.js
index 0367e412d35489bd8b028ae08d00bcc3db952795..b36d33e63283c29be15cc7d39ead60278e37ae88 100644
--- a/src/transaction/TransactionList.js
+++ b/src/transaction/TransactionList.js
@@ -34,7 +34,7 @@ function TransactionList() {
   if (proxy) {
     query += "&proxy=" + proxy.num;
   }
-  query += types.map((t) => "&type=" + engType[t]);
+  query += types.map((t) => "&type=" + engType[t]).join("");
 
   const onTypeChange = (e) => {
     const newTypes = Array.from(e.target.selectedOptions, (o) => o.value);