diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..e69de29
diff --git a/SOLUCION.md b/SOLUCION.md
new file mode 100644
index 0000000..1ae0835
--- /dev/null
+++ b/SOLUCION.md
@@ -0,0 +1,17 @@
+# Ignacio González Pozo - igonzalezp@gmail.com
+
+Fase A - Escenarios de prueba whatsapp
+
+Herramientas: Gherkin
+
+Ubicacion:
+src/test/java/challenge.faseA
+
+
+Fase B - Desarrollo Kata09: Back to the Checkout
+
+Herramientas: Java - junit - Maven
+
+Ubicacion:
+src/java/challenge.faseB
+src/test/java/challenge.faseB
diff --git a/pom.xml b/pom.xml
new file mode 100644
index 0000000..0dcdf2a
--- /dev/null
+++ b/pom.xml
@@ -0,0 +1,76 @@
+
+
+
+ 4.0.0
+
+ challenge
+ qachallenge
+ 1.0-SNAPSHOT
+
+ qachallenge
+
+
+
+ UTF-8
+ 1.7
+ 1.7
+
+
+
+
+ junit
+ junit
+ 4.11
+ test
+
+
+
+
+
+
+
+
+
+
+ maven-clean-plugin
+ 3.1.0
+
+
+
+ maven-resources-plugin
+ 3.0.2
+
+
+ maven-compiler-plugin
+ 3.8.0
+
+
+ maven-surefire-plugin
+ 2.22.1
+
+
+ maven-jar-plugin
+ 3.0.2
+
+
+ maven-install-plugin
+ 2.5.2
+
+
+ maven-deploy-plugin
+ 2.8.2
+
+
+
+ maven-site-plugin
+ 3.7.1
+
+
+ maven-project-info-reports-plugin
+ 3.0.0
+
+
+
+
+
diff --git a/src/main/java/challenge/faseB/CheckOut.java b/src/main/java/challenge/faseB/CheckOut.java
new file mode 100644
index 0000000..d62981b
--- /dev/null
+++ b/src/main/java/challenge/faseB/CheckOut.java
@@ -0,0 +1,110 @@
+package challenge.faseB;
+
+import java.text.DecimalFormat;
+import java.util.Map;
+import java.util.TreeMap;
+
+/**
+ * Contiene carro de compra y aplica descuentos de acuerdo a promociones actuales
+ */
+
+public class CheckOut {
+ //Items en carro de compras
+ private Map checkedItems = new TreeMap<>();
+
+ //Valor total a pagar
+ private Double totalPrice = 0.0;
+
+ //Recibe promociones actuales
+ private Map promotionRules;
+
+ //Formatea a dos decimales
+ private DecimalFormat decimal = new DecimalFormat("#.##");
+
+ public CheckOut(Map promotionRules) {
+ this.promotionRules = promotionRules;
+ }
+
+ public Double getTotalPrice () {
+ return this.totalPrice;
+ }
+
+ /**
+ * Calcula total a pagar y aplica promociones
+ */
+ public void totalCalculator () {
+ //Total sin descuentos
+ System.out.println("TOTAL: " + decimal.format(totalPrice));
+
+ //Aplica promociones y descuentos en caso de aplicar
+ applyPromotions();
+
+ System.out.println();
+ //Total con descuentos
+ System.out.println("TOTAL PRICE: " + decimal.format(totalPrice));
+ }
+ /**
+ * Añade los items al carro
+ */
+ public void checkItem (String item) {
+ if(checkedItems.containsKey(item))
+ checkedItems.put(item, checkedItems.get(item) + 1);
+ else
+ {
+ checkedItems.put(item, 1);
+ }
+ //Total hasta al momento por cada item añadido, sin descuentos
+ totalPrice = totalPrice + promotionRules.get(item).getUnitPrice();
+ }
+ /**
+ * Aplica promociones al carro de compra
+ */
+ private void applyPromotions() {
+ //Iteracion por items en carro de compras
+ for (Map.Entry entry : checkedItems.entrySet()) {
+
+ //Verifica si item en carro de compras tiene promocion
+ if (promotionRules.containsKey(entry.getKey()) &&
+ promotionRules.get(entry.getKey()).getPromotionRequirement() != null) {
+
+ //Valida tipo promocion a aplicar, en caso de existir mas promociones
+ if (promotionRules.get(entry.getKey()).getPromotionType().equals("MOREFORLESS")) {
+ moreForLess(entry);
+ }
+ }
+ }
+ }
+ /**
+ * Aplica reglas de promocion MOREFORLESS
+ */
+ private void moreForLess (Map.Entry entry) {
+ //Verifica si cumple requisito de promocion
+ if (promotionRules.get(entry.getKey()).getPromotionRequirement() <= entry.getValue()) {
+
+ //Calcula valor sin promocion, cantidad del item * precio unitario
+ Double sumNoPromo = entry.getValue() * promotionRules.get(entry.getKey()).getUnitPrice();
+
+ //Cantidad veces se aplica valor promocion
+ Integer timesPromo = entry.getValue() / promotionRules.get(entry.getKey()).getPromotionRequirement();
+ //Cantidad items sin promocion
+ Integer itemsNoPromo = (entry.getValue() % promotionRules.get(entry.getKey()).getPromotionRequirement());
+
+ //Calcula valor total item aplicando promocion
+ Double sumPromo = (timesPromo * promotionRules.get(entry.getKey()).getPromotionPrice()) +
+ (itemsNoPromo * promotionRules.get(entry.getKey()).getUnitPrice());
+
+ //Calcula descuento aplicado al item, total sin promocion - total con promocion
+ Double discount = sumNoPromo - sumPromo;
+
+ System.out.println("MOREFORLESS Saved " + decimal.format(discount) + " on item " +entry.getKey());
+
+ applyDiscount(discount);
+ }
+ }
+ /**
+ * Aplica descuento al total a pagar
+ */
+ public void applyDiscount (Double discount) {
+ totalPrice = totalPrice - discount;
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/challenge/faseB/Promotion.java b/src/main/java/challenge/faseB/Promotion.java
new file mode 100644
index 0000000..ef42510
--- /dev/null
+++ b/src/main/java/challenge/faseB/Promotion.java
@@ -0,0 +1,36 @@
+package challenge.faseB;
+
+/**
+ * Clase para asignacion de promociones a producto
+ * tipoPromocion, precioPromocion, requisitoPromocion
+ */
+
+public class Promotion {
+ private String promotionType;
+ private Double promotionPrice;
+ private Integer promotionRequirement;
+ private Double unitPrice;
+
+ public Promotion(String promotionType, Double promotionPrice, Integer promotionRequirement, Double unitPrice) {
+ this.promotionType = promotionType;
+ this.promotionPrice = promotionPrice;
+ this.promotionRequirement = promotionRequirement;
+ this.unitPrice = unitPrice;
+ }
+
+ public String getPromotionType(){
+ return this.promotionType;
+ }
+
+ public Integer getPromotionRequirement(){
+ return this.promotionRequirement;
+ }
+
+ public Double getPromotionPrice(){
+ return this.promotionPrice;
+ }
+
+ public Double getUnitPrice(){
+ return this.unitPrice;
+ }
+}
diff --git a/src/main/java/challenge/faseB/PromotionLibrary.java b/src/main/java/challenge/faseB/PromotionLibrary.java
new file mode 100644
index 0000000..eb0d503
--- /dev/null
+++ b/src/main/java/challenge/faseB/PromotionLibrary.java
@@ -0,0 +1,31 @@
+package challenge.faseB;
+
+import java.util.Map;
+import java.util.TreeMap;
+
+/**
+ * Contiene promociones actuales
+ * Item en Promocion, tipoPromocion, precioPromocion, requisitoPromocion
+ *
+ * Precios unitarios por item
+ * "A", 50
+ * "B", 30
+ * "C", 20
+ * "D", 15
+ */
+
+public class PromotionLibrary {
+
+ public static Map promotionIndex = new TreeMap();
+
+ static {
+ promotionIndex.put("A",
+ new Promotion("MOREFORLESS", 130.0,3, 50.0));
+ promotionIndex.put("B",
+ new Promotion("MOREFORLESS", 45.0,2, 30.0));
+ promotionIndex.put("C",
+ new Promotion("MOREFORLESS", null,null, 20.0));
+ promotionIndex.put("D",
+ new Promotion("MOREFORLESS", null,null, 15.0));
+ }
+}
diff --git a/src/main/java/challenge/faseB/Runner.java b/src/main/java/challenge/faseB/Runner.java
new file mode 100644
index 0000000..c65f617
--- /dev/null
+++ b/src/main/java/challenge/faseB/Runner.java
@@ -0,0 +1,41 @@
+package challenge.faseB;
+
+/**
+ * Ignacio González Pozo - igonzalezp@gmail.com
+ * Precios unitarios por item
+ * "A",50
+ * "B",30
+ * "C",20
+ * "D",15
+ */
+public class Runner
+{
+ public static void main( String[] args )
+ {
+
+ CheckOut co = new CheckOut(PromotionLibrary.promotionIndex);
+
+ //Valores para posibles items: A - B - C - D
+ co.checkItem("A");
+ co.checkItem("A");
+ co.checkItem("A");
+ co.checkItem("D");
+ co.checkItem("C");
+ co.checkItem("D");
+ co.checkItem("A");
+ co.checkItem("A");
+ co.checkItem("B");
+ co.checkItem("B");
+ co.checkItem("A");
+ co.checkItem("A");
+ co.checkItem("A");
+ co.checkItem("D");
+ co.checkItem("C");
+ co.checkItem("D");
+ co.checkItem("A");
+ co.checkItem("A");
+ co.checkItem("B");
+ co.checkItem("B");
+ co.totalCalculator();
+ }
+}
diff --git a/src/test/java/challenge/faseA/enviar-documento.feature b/src/test/java/challenge/faseA/enviar-documento.feature
new file mode 100644
index 0000000..3dbfe8a
--- /dev/null
+++ b/src/test/java/challenge/faseA/enviar-documento.feature
@@ -0,0 +1,47 @@
+Feature: Enviar documentos
+ Como usuario de la aplicación whatsapp de telefono Android
+ quiero adjuntar documentos a una conversacion
+ para compartir archivos que tengo en el telefono
+
+ #Given - Dado que
+ #When - Cuando
+ #Then - Entonces
+
+ Background:
+ Given me encuentro en la conversacion "chat xyz"
+
+ Scenario Outline: Adjuntar un documento a la conversacion
+ When se selecciona la opcion de adjuntar documento
+ And envio un
+ Then se muestra recuadro que indica nombre documento y progreso de envio
+ And al finalizar el envio permite descargar el documento
+
+ Examples: #documento: formato de documento a adjuntar
+ | documento |
+ | pdf |
+ | doc |
+ | rar |
+
+
+ Scenario Outline: Cancelar envio de documento a la conversacion
+ When se selecciona la opcion de adjuntar documento
+ And envio un
+ And presiona el progreso del envio para cancelarlo
+ Then el envio se cancela y permite en el mensaje volver a enviarlo
+
+ Examples: #documento: formato de documento a adjuntar
+ | documento |
+ | rar |
+
+
+ Scenario: Adjuntar mas de un documento a la conversacion
+ When se selecciona la opcion de adjuntar documento
+ And envio mas de un documento
+ Then se muestra recuadro que indica nombre y progreso del envio en cada uno
+ And al finalizar el envio permite descargar cada documento
+
+
+ Scenario: Adjuntar documento superior a 99MB
+ When se selecciona la opcion de adjuntar documento
+ And se envia un documento superior a 99MB
+ Then se cancela el envio con mensaje de error "mensaje"
\ No newline at end of file
diff --git a/src/test/java/challenge/faseA/silenciar-conversacion.feature b/src/test/java/challenge/faseA/silenciar-conversacion.feature
new file mode 100644
index 0000000..f9bb7e5
--- /dev/null
+++ b/src/test/java/challenge/faseA/silenciar-conversacion.feature
@@ -0,0 +1,68 @@
+Feature: Silenciar conversacion
+ Como usuario de la aplicación whatsapp de telefono Android
+ quiero silenciar una conversacion
+ para dejar de recibir notificaciones de audio y/o por pantalla cada vez que recibo un mensaje
+
+ #Given - Dado que
+ #When - Cuando
+ #Then - Entonces
+
+ Background:
+ Given la aplicacion whatsapp esta en la pantalla inicial
+
+ Scenario Outline: Silenciar conversacion desde pantalla inicial
+ When selecciona la conversacion "chat xyz" y presiona el icono "Silenciar"
+ And configura rango de tiempo y notificaciones en pantalla
+ Then nuevos mensajes son silenciados y se muestran en pantalla
+ And la conversacion queda silenciada mostrando el icono sin sonido
+
+ Examples: #tiempo: rango de tiempo | 8H <8 horas> - 1W <1 semana> - 1Y <1 año>
+ #mostrar: muestra por pantalla notificaciones | SI - NO
+ | tiempo | mostrar |
+ | 8H | SI |
+ | 1W | NO |
+ | 1Y | SI |
+
+
+ Scenario Outline: Silenciar mas de una conversacion en pantalla principal
+ When selecciona mas de una conversacion "chat xyz" "chat abc" y presiona el icono "Silenciar"
+ And configura rango de tiempo y notificaciones en pantalla
+ Then nuevos mensajes son silenciados y se muestran en pantalla
+ And las conversaciones quedan silenciadas mostrando el icono sin sonido
+
+ Examples: #tiempo: rango de tiempo | 8H <8 horas> - 1W <1 semana> - 1Y <1 año>
+ #mostrar: muestra por pantalla notificaciones | SI - NO
+ | tiempo | mostrar |
+ | 8H | SI |
+ | 1W | SI |
+ | 1Y | NO |
+
+
+ Scenario Outline: Silenciar conversacion mediante menu buscar
+ Given se ha buscado la conversacion "chat xyz" a silenciar
+ When desplega menu de opciones y presiona "Silenciar notificaciones"
+ And configura rango de tiempo y notificaciones en pantalla
+ Then nuevos mensajes son silenciados y se muestran en pantalla
+ And en menu de opciones aparece "Desactivar silencio de notificaciones"
+
+ Examples: #tiempo: rango de tiempo | 8H <8 horas> - 1W <1 semana> - 1Y <1 año>
+ #mostrar: muestra por pantalla notificaciones | SI - NO
+ | tiempo | mostrar |
+ | 8H | SI |
+ | 1W | NO |
+ | 1Y | NO |
+
+
+ Scenario Outline: Silenciar conversacion al interior de conversacion
+ Given me encuentro al interior de la conversacion "chat xyz" a silenciar
+ When desplega menu de opciones de conversacion y selecciona "Silenciar notificaciones"
+ And configura rango de tiempo y notificaciones en pantalla
+ Then nuevos mensajes son silenciados y se muestran en pantalla
+ And en opciones de conversacion aparece "Desactivar silencio de notificaciones"
+
+ Examples: #tiempo: rango de tiempo | 8H <8 horas> - 1W <1 semana> - 1Y <1 año>
+ #mostrar: muestra por pantalla notificaciones | SI - NO
+ | tiempo | mostrar |
+ | 8H | NO |
+ | 1W | SI |
+ | 1Y | SI |
\ No newline at end of file
diff --git a/src/test/java/challenge/faseB/CheckOutTest.java b/src/test/java/challenge/faseB/CheckOutTest.java
new file mode 100644
index 0000000..111e797
--- /dev/null
+++ b/src/test/java/challenge/faseB/CheckOutTest.java
@@ -0,0 +1,73 @@
+package challenge.faseB;
+
+import static org.junit.Assert.*;
+
+import org.junit.Test;
+
+/**
+ * Contiene promociones actuales
+ * Item en Promocion, tipoPromocion, precioPromocion, requisitoPromocion
+ *
+ * Precios unitarios por item
+ * "A", 50
+ * "B", 30
+ * "C", 20
+ * "D", 15
+ */
+public class CheckOutTest
+{
+
+ @Test
+ public void checkItemTest()
+ {
+ CheckOut co = new CheckOut(PromotionLibrary.promotionIndex);
+
+ assertEquals(0.0, co.getTotalPrice(), 0.2);
+
+ //Valores para posibles items: A - B - C - D
+ co.checkItem("A");
+ assertEquals(50.0, co.getTotalPrice(), 0.2);
+
+ co.checkItem("A");
+ assertEquals(100.0, co.getTotalPrice(), 0.2);
+
+ co.checkItem("A");
+ assertEquals(150.0, co.getTotalPrice(), 0.2);
+
+ co.checkItem("D");
+ assertEquals(165.0, co.getTotalPrice(), 0.2);
+
+ co.checkItem("C");
+ assertEquals(185.0, co.getTotalPrice(), 0.2);
+
+ co.checkItem("B");
+ assertEquals(215.0, co.getTotalPrice(), 0.2);
+
+ co.checkItem("B");
+ assertEquals(245.0, co.getTotalPrice(), 0.2);
+ }
+
+ @Test
+ public void totalCalculatorTest()
+ {
+ CheckOut co = new CheckOut(PromotionLibrary.promotionIndex);
+
+ //Valores para posibles items: A - B - C - D
+ co.checkItem("A");
+ co.checkItem("A");
+ co.checkItem("A");
+ co.checkItem("D");
+ co.checkItem("C");
+ co.checkItem("B");
+ co.checkItem("B");
+ co.checkItem("B");
+ co.checkItem("D");
+ co.checkItem("A");
+ co.checkItem("A");
+ co.checkItem("B");
+
+ co.totalCalculator();
+
+ assertEquals(370.0, co.getTotalPrice(), 0.2);;
+ }
+}