You are on page 1of 95

Tecnológico de Estudios

Superiores de Ecatepec
Proyecto:
Comercio electrónico

Alumno:
Miguel Angel Guillen Suarez

Matricula:
201221389

Asesor interno:
Profesora M. en C. Dora Araceli Cruz Huerta

0
Índice

1. Introduccion

1.1Objetivos del Proyecto

2. Análisis del Proyecto

2.1 Descripción del sistema deseado

2.2 Propósito, alcance, objetivos y justificacion

3. Herramientas Utilizadas

4. Análisis y Diseño

4.1 Requerimientos específicos

4.2 Diagramas UML

4.2.1 Diagrama de clases UML

4.3 Diagrama de Casos de uso


4.3.1 Descripcion del diagrama de casos de uso
4.4 Diagramas de secuencia
4.5 Diagramas de actividades
5. Desarrollo
6. Implementacion
7. Conclusiones
8. Bibliografia

1
1. Introduccion

La razón principal por la que tome la decisión de realizar este proyecto es para
acreditar las residencias profesionales basado en las tecnologías, por el deseo de
aprender y profundizar en el conocimiento del desarrollo de aplicaciones en una
plataforma moderna, la cual se encuentra en constante actualización y que además
considero que en concreto este trabajo permitirá repasar los conceptos fundamentales
adquiridos durante la carrera y poder aplicarlos para una solución que aunque teórica
consta de muchos componentes que se aplican en el campo profesional.

1.1Objetivos del Proyecto

El proyecto deberá contener las siguientes características:

 La página puede ser gestionada por una persona o más, que tendrán el
rango de administrador. Se entiende por gestión, la capacidad de poder
insertar o eliminar categorías y productos además de poder cambiar el título
de la página y la interfaz gráfica de la misma.

 Los productos deben pertenecer a una categoría y deben tener una


fotografía.

 Los usuarios podrán realizar compras, consultar compras realizadas, y


contactar por la tienda vía email.

 Los productos que el usuario registrado quiera comprar se irán insertando en


un carrito, cuya función será almacenar esos productos hasta que finalice la
compra.

 El usuario debe de ser capaz de eliminar productos del carrito en cualquier


momento antes de finalizar a la compra.

 Se enviará un email al comprador en el momento en que se haga la compra.

 La página web de la tienda deberá poderse ver desde cualquier sistema con
un navegador.

2. Análisis del Proyecto

2.1 Descripción del sistema deseado

Se pretende realizar una aplicación web que facilite a los dueños de tiendas la
posibilidad de crear una tienda web de la manera más sencilla posible, en la que no
haga falta muchos conocimientos sobre informática. Para ello se usarán tecnologías
modernas para su creacion.

2
2.2 Propósito, alcance, objetivos y justificacion

Propósito: Estimular los negocios de compra-venta en internet, de una forma fácil y


sencilla.

Alcance: El proyecto es aplicable a cualquier negocio en el que se venda cualquier


cosa, ya sea un particular o una empresa. Que la página pueda ser cargada desde
cualquier navegador.

Objetivos: El proyecto tiene pues como objetivo permitir la operacion de tiendas a


cualquier usuario, permitiendo, mediante el tratamiento de la información y el uso de
interfaces gráficas, un acceso a los datos sencillo, rápido, libre de fallos y seguro.
Hacer que la aplicación alcance un nivel de eficiencia máximo.

Justificación: La aparición de sitios web no ya solo para la obtención de información,


sino que también para la realización de transacciones de compra y venta a lo que
técnicamente se le denomina como e-commerce. Las ventajas que nos ofrece internet
y el cómo poder aprovecharlas para que la empresa pueda ofrecer sus productos de
forma inmediata el cualquier parte del mundo, con unos costes mínimos ya que no
necesita tener un local físico ni horarios de tienda por lo que, se puede visitar la tienda
a cualquier horario y esto se hace imprescindible para una tienda moderna disponer de
este tipo de herramientas para poder realizar su actividad y los potenciales clientes los
cuales pueden optar por una variedad de productos a lo largo y ancho de toda la red
para elegir la opción qua más les convenga.

3. Herramientas Utilizadas

IDE eclipse, el lenguaje de programación Apex (muy similar a java), para la base de
datos es Oracle y para la página web HTML 5 y bootstrap

Lenguaje de programación: Apex es un lenguaje de secuencia centrado en objetos y


muy definido que permite a los desarrolladores ejecutar declaraciones de control de
transacciones y flujos en el servidor de la plataforma de Force.com junto con llamadas
a la API de Force.com. Gracias a una sintaxis parecida a Java y un funcionamiento
similar a los procedimientos almacenados en una base de datos, Apex permite a los
desarrolladores agregar la lógica de negocio a la mayoría de los eventos del sistema,
entre los que se incluyen el hacer clic en los botones, las actualizaciones de registros
relacionados y las páginas de Visualforce. Los códigos de Apex pueden iniciarse
mediante solicitudes de servicio Web y a partir de desencadenadores en objetos.

Visualforce es un marco que permite a los desarrolladores crear interfaces de usuario


personalizadas sofisticadas que se pueden alojar de forma nativa en la plataforma de
Force.com. El marco de Visualforce incluye un lenguaje de marca basado en etiquetas,
similar a HTML, Bootstrap, CSS y JavaScript con un conjunto de “controladores

3
estándar” del lado del servidor que realizan operaciones de base de datos básicos,
como consultas y guardados, muy fáciles de realizar
IDE Eclipse

Eclipse es un entorno de desarrollo integrado, de Código abierto y Multiplataforma.


Mayoritariamente se utilliza para desarrollar lo que se conoce como Aplicaciones de
Cliente Enriquecido, entorno de desarrollo integrado, opuesto a las aplicaciones
Cliente-liviano, entorno de desarrollo integrado basadas en navegadores. Es una
potente y completa plataforma de Programación, desarrollo y compilación de elementos
tan variados como sitios web, programas en C++ o aplicaciones Java. No es más que
un entorno de desarrollo integrado (IDE) en el que encontrarás todas las herramientas
y funciones necesarias para tu trabajo, recogidas además en una atractiva interfaz que
lo hace fácil y agradable de usar.

4. Análisis y Diseño

Las funciones a realizar son las siguientes:


· Consulta según categoría.
· Consulta de los detalles de un artículo.
· Consulta de novedades.
· Consulta del carrito.

‐ Modificación del carrito.

· Añadir articulo al carrito.


· Eliminar articulo del carrito.
· Modificar cantidad en el carrito.

‐ Tratamiento de usuarios.
· Insertar cliente .
· Modificar datos.
· Mostrar información.

‐ Modificación de los articulos.


· Insertar articulo.
· Eliminar articulo
· Modificararticulo

‐ Operaciones sobre los pedidos.


· Búsqueda de pedidos por cliente.

4
· Modificación del estado de un pedido.
· Insertar pedido.
4.1 Requerimientos específicos

Consulta según categoría.


Estas categorías aparecerán en el submenú, desde el cual, el cliente podrá
seleccionar la que desee y así serán mostrados todos y cada uno de los artículos
pertenecientes a esa categoría.
Consulta de los detalles de un articulo.
Con esta consulta, el cliente podrá ver información mas detallada acerca del articulo
que desee. Pinchando en “ver detalles” del articulo que se desee, está acción
devolverá todos los detalles del articulo y serán mostrados.
Consulta de novedades.
Desde la pagina principal, una vez se abre la pagina de inicio (principal) aparecen
todos los artículos referenciados como novedad.
Consulta del carrito.
El cliente podrá consultar en todo momento los artículos que ha seleccionado para
ser comprados. Desde el marco situado en la derecha de la pagina en el que aparece
el resumen del carrito, pinchando en el botón “carrito”, se accederá a la pantalla que
muestra la tabla con todos los artículos añadidos al carrito.
Añadir artículo al carrito.
Cualquier usuario que entre a la pagina podrá añadir artículos en el carrito. Estos
artículos se añaden simplemente desde la pantalla de los detalles del producto
pinchando en el botón “Añadir a carrito”.
Eliminar artículo del carrito.
Desde la pagina de detalles del carrito, el cliente puede eliminar todos los artículos
que desee. La tabla que muestra los artículos que hay en el carrito, dispone de la
columna “Eliminar” para cada artículo que se desee eliminar.
Modificar cantidad en el carrito.
La columna “cantidad” que contiene un textbox para cada articulo indicando el
numero de unidades que se desea comprar. En caso de querer modificarse, el cliente
tendrá que modificar el numero de cantidad que desea segn sea el caso para agragar
“+” o para quitar ”-” y de tal forma modifiacar la cantidad.

5
Insertar cliente en la base de datos.
Esta función la tendrá que realizar todo usuario que desee realizar una compra en la
TV y no la haya realizado previamente. Mediante un formulario sencillo, el cliente no
registrado rellenará todos los campos necesarios con sus datos personales. En caso
de dejarse algún campo por rellenar, el sistema generará un error visual para el
cliente que tendrá que rellenarlo de nuevo.

Insertar articulo
Un sencillo formulario permite a los empleados agregar nuevos artículos en la base
de datos. Además podrá subir la imagen de dicho articulo.
4.2Diagrama UML
Para entender mejor todas las funciones que se pueden realizar con esta tienda virtual
y los elementos y objetos de los cuales está compuesta se han realizado los diagramas
UML. A continuación se detallan brevemente las características de la aplicación en
base a este diagrama.
La Tienda Virtual como bien indica su nombre es la aplicación en si, entorno a la cual
se realizan la mayoría de funciones. El Empleado y el Usuario serán las clases que
interactúen con este a través del Stock.
Stock es una clase que contiene todos los elementos de los que se compone la Tienda
Virtual. Contiene un numero indefinido de productos que son los que forman la clase
Stock. Todas las consultas realizadas por el Usuario se harán a esta clase.

6
7
4.2.1Diagrama de clases UML

8
4.3 Diagramas de Casos de uso
Para un entendimiento más intuitivo de las acciones que se pueden realizar, al menos
las más importantes, se adjunta una figura resumiendo dichas funciones.

4.3.1Descripcion de los diagramas de casos de uso

Caso de uso Añadir a carrito

Descripción El usuario añade un producto al carrito.

Actor iniciador Usuario

Actores secundarios ‐

Resumen Cualquier usuario podrá añadir el producto de la


Tienda Virtual que desee al carrito en cualquier
momento sea usuario registrado o anónimo.

Precondiciones ‐

Postcondiciones El sistema actualizará el resumen del carrito.

Flujo de eventos Interacciones del Obligaciones del


usuario sistema

9
1. El usuario selecciona 2. El sistema busca en la
un producto en el base de datos las
catálogo. características del
producto.
4. El sistema
3. El usuario pulsa sobre comprueba que el
el botón “Añadir a carrito” producto se
del producto deseado. encuentre en el carrito.
5. Si se encuentra,
suma la cantidad al
producto existente en el
carrito.
6. Si no se
encuentra, se añade el
articulo nuevo al carrito.
7. El sistema
actualiza los
totales del carrito.

Extensiones síncronas En 3 el usuario puede cancelar la operación.

Extensiones ‐
asíncronas
Caso de uso Eliminar del carrito

Descripción El usuario elimina un producto al carrito

Actor iniciador Usuario

Actores secundarios ‐

Resumen Cualquier usuario podrá eliminar un producto del


carrito en el momento que desee.
Precondiciones El producto debe haber sido añadido al carrito
anteriormente.
Postcondiciones El sistema actualizará el resumen del carrito.

Flujo de eventos Interacciones del usuario Obligaciones del sistema

10
El usuario va a la Elimina del carrito el
pagina donde se producto seleccionado.
encuentra el
resumen del carrito. 4. Actualiza el carrito.

Extensiones síncronas En 3 el usuario puede cancelar la operación. Si el usuario


elimina todos los elementos del carrito el sistema
mostrará que el carrito está vacío.

Extensiones asíncronas ‐

Caso de uso Modificar cantidad.

Descripción El usuario modifica la cantidad de un producto añadido al


carrito.
Actor iniciador Usuario

Actores secundarios ‐

Resumen Cualquier usuario podrá modificar la cantidad de un


producto que desee adquirir.
Precondiciones El producto debe haber sido añadido al carrito
anteriormente.
Postcondiciones El sistema actualizará el resumen del carrito.

Flujo de eventos Interacciones del usuario Obligaciones del sistema

11
1. El usuario va a la
pagina donde se
encuentra el
resumen del carrito.

2. Modifica la cantidad
4. Actualiza los totales
de el/los producto/s que
del carrito.
desee cambiar.

Extensiones síncronas En 3 el usuario puede cancelar la operación. Si el usuario


modifica todas cantidades a cero, el sistema mostrará un
mensaje indicando que el carrito está vacío.

Extensiones asíncronas ‐

12
4.4 Diagramas de secuencia
A continuación se muestran varios ejemplos de interacción con el sistema
representados mediante unos diagramas de secuencia que reflejan a nivel de ejecución
los pasos que sigue la aplicación para llevar a cabo las acciones indicadas arriba de
cada ejemplo. Se muestra un ejemplo para el empleado y otro para el usuario

13
• Añadir articulo a la base de datos

14
• Añadir articulo al carrito.

15
4.5 Diagrama de Actividades

Enlaces

Diagrama de actividades de enlaces


Buscar productos:

Diagrama de actividades e buscar productos

16
Añadir al carrito:

Diagrama de actividades de añadir al carrito

Datos personales:

Diagrama de actividades de datos personales

Contacto:

Diagrama de actividades de contacto

Interfaz de la tienda:

17
Diagrama de actividades de la interfaz de la tienda

Modificar catálogo:

diagrama de actividades de modificar catálogo

Modificar productos:

18
Diagrama de actividades de modificar productos

Carro:

Diagrama de actividades del carro

5 .Desarrollo

Se expone el código desarrollado

Clases ápex

~ AuthorizeDotNet

19
/*
description : This is the main Lib class which handles and contains all methods repres
enting
transaction related to authorize.net, you first need to set your merchant login
and transkey
then call transaction method then process method.
*/
public class AuthorizeDotNet{
//Set Merchant's Login id and transaction key
private static final string login = '484H7fmfS24';
private static final string transkey = '5vz9c9c4mJzVW32v';

//Class level useful variables


private list<string> results;
private boolean approved;
private boolean declined;
private boolean error;
private string url;
private boolean isTest;
private string fields;
private string response;
private map<string, string> params;

public AuthorizeDotNet(boolean isTest){


results = new list<string>();
approved = false;
declined = false;
error = true;
fields = '';
params = new map<string, string>();

//For setting sandbox or production


this.isTest = isTest;
if (this.isTest){
this.url = 'https://test.authorize.net/gateway/transact.dll';
}
else {
this.url = 'https://secure.authorize.net/gateway/transact.dll';
}

//Some Predefined useful parameters for authorize.net API


params.put('x_delim_data', 'true');
params.put('x_delim_char', '|');
params.put('x_relay_response', 'false');
params.put('x_url', 'false');
params.put('x_version', 'false');

20
params.put('x_method', 'CC');
params.put('x_type', 'AUTH_CAPTURE');
params.put('x_login', login);
params.put('x_tran_key', transkey);
params.put('x_description', 'Sample Transaction');
params.put('x_description', '0');

public void transaction(string cardnum, string expiration, string amount, string cvv, stri
ng invoice, string tax){
params.put('x_card_num', cardnum);
params.put('x_exp_date', expiration);
params.put('x_amount', amount);
params.put('x_po_num', invoice);
params.put('x_tax', tax);
params.put('x_card_code', cvv);
}

//Calls the Authorize.Net service and fetch the response


public void process(integer retries){
retries = 3;
this.prepareParameters();

integer count = 0;
while (count < retries){
HttpRequest hReq = new HttpRequest();
hReq.setEndpoint(this.url);
hReq.setMethod('POST');
hReq.setBody(this.fields);
Http con = new Http();
if(!Test.isRunningTest()){
HttpResponse res = con.send(hReq);
this.response = res.getBody();
}else{
//Test response filling in case Test class is running
this.response = '1|1|1|This transaction has been approved.|LDV9JR|Y|
2160295577||0|600.00|CC|auth_capture||aslam|bari||dfsdf||wa|5555||||||||||||||||||
71AFA2003D02930E47E84F23E14E07C3|P|2|||||||||||XXXX1111|Visa|||||||||||||||||false|1';
}
system.debug('#### ' + this.response);
this.parseResults();
if (this.getResultResponseFull() == 'Approved'){
this.approved = true;
this.declined = false;
this.error = false;

21
break;
}
else if (this.getResultResponseFull() == 'Declined'){
this.approved = false;
this.declined = true;
this.error = false;
break;
}
count++;
}
}

private void parseResults(){


this.results = this.response.split('\\|');
}

public void setParameter(String param, String value){


param = param.trim();
value = value.trim();
this.params.put(param, value);
}

public void setTransactionType(String types){


this.params.put('x_type', types.toUpperCase().trim());
}

private void prepareParameters(){


for(String ss: params.keyset()){
this.fields += ss + '=' + EncodingUtil.UrlEncode(params.get(ss),'UTF-8') + '&';
}
this.fields = this.fields.substring(0,this.fields.length() - 1);
}

public string getResultResponse(){


return this.results[0];
}

public string getResultResponseFull(){


list<string> response = new list<string>();
response.add('');
response.add('Approved');
response.add('Declined');
response.add('Error');
if(this.results[0] == '1')
return response[1];
else if(this.results[0] == '2')

22
return response[2];
else if(this.results[0] == '3')
return response[3];

return '';
}

public boolean isApproved()


{
return this.approved;
}

public boolean isDeclined()


{
return this.declined;
}

public boolean isError()


{
return this.error;
}

public string getResponseText()


{
return this.results[3];
}

public string getAuthCode()


{
return this.results[4];
}

public string getAVSResponse()


{
return this.results[5];
}

public string getTransactionID()


{
return this.results[6];
}

~ CartController

23
public with sharing class CartController {

public List<Product2> productList2 {get; set;}


public String clave {get; set;}
public String cat {get; set;}
public String paq {get; set;}
public String cart {get; set;}
//variables para dejar un mensaje
public Contact contacto {get; set;} //se usa el campo de email para validar que sea un
email correcto
public String nombre {get; set;}
public String asunto {get; set;}
public String mensajem {get; set;}

//dependiendo de los parametros cambian los productos por eso es una consulta difer
ente desde el constructor
public CartController(ApexPages.StandardController stdController) {

contacto = new Contact();


clave = apexpages.currentpage().getparameters().get('prod');
cat = apexpages.currentpage().getparameters().get('cat');
paq = apexpages.currentpage().getparameters().get('paq');
cart = apexpages.currentpage().getparameters().get('cart');

if(clave==''|| clave == NULL){//si no hay clave de producto


searchProducts();
}
else{ //si hay clave del producto
searchProductsClave();
}

public PageReference searchProducts()


{
if(cat==''|| cat == NULL){ //si no hay categoria
productList2 = [SELECT Id, Name, Description, Categoria__c, Marca__c,ImgId__c
FROM Product2
WHERE IsActive = TRUE LIMIT 9];

return null;
}
else{ //si hay Categoría
if(paq=='si'){ //si es paquete
productList2 = [SELECT Id, Name, Description, Categoria__c, Marca__c,ImgId__

24
c
FROM Product2
WHERE Categoria__c =: cat AND (IsActive = TRUE AND Marca__c = 'Genéric
a') LIMIT 9];

return null;
}
else{//si no es paquete
productList2 = [SELECT Id, Name, Description, Categoria__c, Marca__c,ImgId__
c
FROM Product2
WHERE Categoria__c =: cat AND IsActive = TRUE LIMIT 9];

return null;
}

public PageReference searchProductsClave()


{

productList2 = [SELECT Id, Name, Description, Categoria__c, Marca__c,ImgId__c


FROM Product2
WHERE Name LIKE: '%'+ clave +'%' AND IsActive = TRUE LIMIT 9];

return null;
}

public PageReference dejarMensaje(){


Messaging.SingleEmailMessage message = new Messaging.SingleEmailMessage()
;
message.toAddresses = new String[] { 'edgar.popoca@gmail.com' };
//message.optOutPolicy = 'FILTER';
message.subject = asunto;
message.plainTextBody = mensajem;
message.setSenderDisplayName(nombre);
message.setReplyTo(contacto.email);

Messaging.SingleEmailMessage[] messages = new List<Messaging.SingleEmailMe


ssage> {message};
Messaging.SendEmailResult[] results = Messaging.sendEmail(messages);

25
if (results[0].success) {
System.debug('The email was sent successfully.');

} else {

System.debug('The email failed to send: ' + results[0].errors[0].message);


}
PageReference page = new PageReference('/home?cart='+cart);

return page;
}

public PageReference aCarrito(){


if(cart=='' || cart == NULL){
return null;
}
else{
PageReference page = new PageReference('/Shoppingcart?id='+cart);

return page;
}

/*Esto seria mejor si quisieramos actualizar los reg cada que lo llamamos pero en este
caso los productos no cambian so en el constructor
esta bien
//lista de todos los productos activos existentes
public List<Product2> getProductos(){
return [SELECT Id, Name, Description, Categoria__c, Marca__c
FROM Product2
WHERE IsActive = TRUE LIMIT 1];
}*/

/*public void buscar(){


productList2 = [SELECT Id, Name, Description, Categoria__c, Marca__c,ImgId__c
FROM Product2
WHERE Name LIKE: '%'+ 'ro' +'%' AND IsActive = TRUE LIMIT 9];
update productList2;

}*/

~ ChangePasswordController

26
/**
* An apex page controller that exposes the change password functionality
*/
public with sharing class ChangePasswordController {
public String oldPassword {get; set;}
public String newPassword {get; set;}
public String verifyNewPassword {get; set;}

public PageReference changePassword() {


return Site.changePassword(newPassword, verifyNewPassword, oldpassword);
}

public ChangePasswordController() {}
}

ChangePasswordControllerTest

/**
* An apex page controller that exposes the change password functionality
*/
@IsTest public with sharing class ChangePasswordControllerTest {
@IsTest(SeeAllData=true) public static void testChangePasswordController() {
// Instantiate a new controller with all parameters in the page
ChangePasswordController controller = new ChangePasswordController();
controller.oldPassword = '123456';
controller.newPassword = 'qwerty1';
controller.verifyNewPassword = 'qwerty1';

System.assertEquals(controller.changePassword(),null);
}
}

~ CheckoutController

public with sharing class CheckoutController {

public List<OpportunityLineItem> productos {get; set;}

public Opportunity venta {get; set;}

public String oliIdChosen {get; set;}

public CheckoutController(ApexPages.StandardController stdController) {


venta = [SELECT Id, Name, Amount, Estado_compra__c, CloseDate, Account.Name

27
,
Tipo_de_tarjeta__c, Numero_de_tarjeta__c, Codigo_de_la_tarjeta__c, Nombre_en
_tarjeta__c,
Fecha_de_expiracion__c
FROM Opportunity
WHERE Id =: stdController.getId()];

productos = [SELECT Id, Name,UnitPrice, ListPrice, Product2.Name, Quantity, TotalP


rice,Product2.ImgId__c, Product2.Description
FROM OpportunityLineItem WHERE Opportunity.id =:venta.Id ];

public PageReference seguirComprando(){

PageReference page = new PageReference('/home?cart='+venta.Id);


page.setRedirect(true);
return page;
}

public PageReference proceder(){


PageReference page = new PageReference('/Checkout?id='+venta.Id);
page.setRedirect(true);
return page;

public PageReference aumentar(){


update productos;
OpportunityLineItem toDel = [SELECT id, Name, Quantity, UnitPrice FROM Opportun
ityLineItem WHERE id=: oliIdChosen];
toDel.Quantity +=1;
update toDel;
PageReference page = new PageReference('/ShoppingCart?id='+venta.Id);
page.setRedirect(true);
return page;
}

public PageReference restar(){


update productos;
OpportunityLineItem toDel = [SELECT id, Name, Quantity, UnitPrice FROM Opportun
ityLineItem WHERE id=: oliIdChosen];
if(todel.Quantity>1)//{
toDel.Quantity -=1;

28
update toDel;
PageReference page = new PageReference('/ShoppingCart?id='+venta.Id);
page.setRedirect(true);
return page;
/*}
else{
delete toDel;
PageReference page = new PageReference('/Shoppingcart?id='+venta.Id);
return page;
}*/

public PageReference eliminar(){


update productos;
OpportunityLineItem toDel = [SELECT id, Name FROM OpportunityLineItem WHERE
id=: oliIdChosen];
System.debug(toDel.Id);
delete toDel;
PageReference page = new PageReference('/ShoppingCart?id='+venta.Id);
page.setRedirect(true);
return page;

~ DoPaymentHandler

/*
description : The class is the controlling for Checkout page. It handles the all form field
s
and gives to AuthorizeDotNet class to process the actual payment. It also set
s
the amount to the opportunity amount and creates the account if necessary.
*/
public class DoPaymentHandler{
/*public string amount{get;set;}*/
/*cambiamos el get set por personalizados y obtenemos el amount de la oportunidad
a traves del parametro*/
public string amount;
public Opportunity venta {get; set;}

29
public Account cuenta {get; set;}
public Account cuentaEx {get; set;} //variable para ver si existe cuenta con ese mail
List<Account> cuentasEx {get; set;} //Lista para que si el querry viene vacio no me
marque error(no asignar directamente a una cuenta)

public string firstname{get;set;}


public string lastname{get;set;}
public string email{get;set;}
public string address{get;set;}
public string city{get;set;}
public string state{get;set;}
public string zip{get;set;}
public string cardholder{get;set;}
public string cardnumber{get;set;}
public string cardyear{get;set;}
public string cardmonth{get;set;}
public string cardcvv{get;set;}
public string expiration{get;set;}
public string selectedCardType{get;set;}

public boolean isSuccess{get;set;}

public DoPaymentHandler(ApexPages.StandardController stdController){


venta = [SELECT Amount
FROM Opportunity
WHERE Id =: stdController.getId()];

/*cuentaEx = null;
cuentasEx = [SELECT Id, Name, Correo_electronico__c FROM Account WHERE
Correo_electronico__c = 'edgar@romero.com' LIMIT 1];
if(!cuentasEx.isEmpty()){
cuentaEx = cuentasEx[0];
}*/

/*El getter que le asigna el amount al total de la oportunidad*/


public String getAmount()
{
if (amount == null)
{
amount = venta.Amount.toPlainString();
}

30
return amount;
}
/*Setter por si se llegara a usar*/
public void setAmount(String s)
{
amount = s;
}

public List<SelectOption> getMonths(){


list<SelectOption> months = new list<SelectOption>();
months.add(new selectOption('01','Jan'));
months.add(new selectOption('02','Feb'));
months.add(new selectOption('03','Mar'));
months.add(new selectOption('04','Apr'));
months.add(new selectOption('05','May'));
months.add(new selectOption('06','Jun'));
months.add(new selectOption('07','Jul'));
months.add(new selectOption('08','Aug'));
months.add(new selectOption('09','Sep'));
months.add(new selectOption('10','Oct'));
months.add(new selectOption('11','Nov'));
months.add(new selectOption('12','Dec'));
return months;
}

public List<SelectOption> getYears(){


list<SelectOption> years = new list<SelectOption>();
integer curMonth = system.today().year();
for(integer i=1;i<10;i++){
years.add(new selectOption(curMonth + '',curMonth++ + ''));
}
return years;
}

public List<SelectOption> getCardTypes(){


list<SelectOption> cardtype = new list<SelectOption>();
cardtype.add(new selectOption('Visa','Visa'));
cardtype.add(new selectOption('Master Card','Master Card'));
cardtype.add(new selectOption('American Express','American Express'));
return cardtype;
}

//Handling payment processing submitting by VF page button


public void process(){
isSuccess = false;

31
expiration = cardmonth + cardyear;

if(!validate()){
isSuccess = false;
return;
}
AuthorizeDotNet ath = new AuthorizeDotNet(true);
ath.transaction(cardnumber, expiration, amount, cardcvv,'','');
ath.setParameter('x_device_type','1');
ath.setParameter('x_first_name',firstname);
ath.setParameter('x_last_name',lastname);
ath.setParameter('x_address',address);
ath.setParameter('x_state',state);
ath.setParameter('x_response_format','1');
ath.setParameter('x_zip',zip);
try{
ath.process(3);
}catch(Exception ex){
ApexPages.addmessage(new ApexPages.message(ApexPages.severity.Error,
ex.getMessage()));
isSuccess = false;
}

if(ath.isApproved()){
String responsetext = ath.getResponseText();
String transactionid = ath.getTransactionID();
ApexPages.addmessage(new ApexPages.message(ApexPages.severity.Info, re
sponsetext + '\nTransaction Id: ' + transactionid ));
ApexPages.addmessage(new ApexPages.message(ApexPages.severity.CONFI
RM, '\nSu pago fue aprobado, en breve recibirá un correo con el detalle de su compra.')
);
isSuccess = true;
//Si ya existe la cuenta se asigna a cuantaEx, si no existe se le asigna NULL
cuentaEx = null;
cuentasEx = [SELECT Id, Name, Correo_electronico__c FROM Account WHE
RE Correo_electronico__c =: email LIMIT 1];
if(!cuentasEx.isEmpty()){
cuentaEx = cuentasEx[0];
}

if(cuentaEx ==NULL){ //se crea cuenta y se le asigna a la oportunidad


cuenta = new Account();
cuenta.Correo_electronico__c = email;
cuenta.Name = firstname + ' ' + lastname;
DateTime d = Date.Today() ;
String dateStr = d.format('dd/MM/yyyy') ;

32
cuenta.Description = 'Cuenta generada a partir de una compra por internet el dí
a ' + dateStr;
cuenta.ShippingCity = city;
cuenta.ShippingState = state;
cuenta.ShippingPostalCode = zip;
//falta pedir country pero ya se sabe con state y city
cuenta.ShippingStreet = address;
insert cuenta;

venta.AccountId = cuenta.id;
venta.Name = 'Id de la transacción: '+ transactionid+ ' '+firstname + ' ' + lastnam
e + ' ' +dateStr;
venta.StageName = 'Closed Won';
venta.CloseDate = System.today();
venta.Estado_compra__c = 'Comprado';
venta.Numero_de_tarjeta__c = cardnumber;
venta.Tipo_de_tarjeta__c = selectedCardType;
venta.Codigo_de_la_tarjeta__c = cardcvv;
venta.Fecha_de_expiracion__c = cardyear;
venta.Nombre_en_tarjeta__c = cardholder;
venta.email__c = email;
update venta;
}
else{ //solo se asigna la cuenta ya existente a la oportunidad
DateTime d = Date.Today() ;
String dateStr = d.format('dd/MM/yyyy') ;
venta.AccountId = cuentaEx.id;
venta.Name = 'Id de la transacción: '+transactionid+' '+ firstname + ' ' + lastnam
e + ' ' +dateStr;
venta.StageName = 'Closed Won';
venta.CloseDate = System.today();
venta.Estado_compra__c = 'Comprado';
venta.Numero_de_tarjeta__c = cardnumber;
venta.Tipo_de_tarjeta__c = selectedCardType;
venta.Codigo_de_la_tarjeta__c = cardcvv;
venta.Fecha_de_expiracion__c = cardyear;
venta.Nombre_en_tarjeta__c = cardholder;
venta.email__c = email;
update venta;
}

/* Messaging.SingleEmailMessage message = new Messaging.SingleEmailMess


age();
message.toAddresses = new String[] { email };
//message.optOutPolicy = 'FILTER';
message.setTemplateId('00Xf4000000IBih');

33
message.setWhatId(venta.Id);

//message.subject = 'Seguimiento de tu compra';


//message.plainTextBody = 'hmmm';
message.setSenderDisplayName('CompuSoluciones');
message.setReplyTo('contacto@compusoluciones.com');

Messaging.SingleEmailMessage[] messages = new List<Messaging.SingleEm


ailMessage> {message};
Messaging.SendEmailResult[] results = Messaging.sendEmail(messages);

if (results[0].success) {
System.debug('The email was sent successfully.');

} else {

System.debug('The email failed to send: ' + results[0].errors[0].message);


}*/
}
else if(ath.isDeclined()){
String reason = ath.getResponseText();
ApexPages.addmessage(new ApexPages.message(ApexPages.severity.Error, r
eason));
isSuccess = false;
}
else{
String reason = ath.getResponseText();
ApexPages.addmessage(new ApexPages.message(ApexPages.severity.Error, r
eason));
isSuccess = false;
}
}

private boolean validate(){


boolean isvalid = true;
if(!isValid(amount)){
ApexPages.addmessage(new ApexPages.message(ApexPages.severity.Error, '
Falta el Campo Obligatorio: Total a pagar'));
isvalid = false;
}
if(!isValid(cardnumber)){
ApexPages.addmessage(new ApexPages.message(ApexPages.severity.Error, '
Falta el Campo Obligatorio: Número de Tarjeta'));
isvalid = false;
}

34
if(!isValid(expiration)){
ApexPages.addmessage(new ApexPages.message(ApexPages.severity.Error, '
Falta el Campo Obligatorio: Fecha de expiración'));
isvalid = false;
}
if(!isValid(cardcvv)){
ApexPages.addmessage(new ApexPages.message(ApexPages.severity.Error, '
Falta el Campo Obligatorio: Código de tarjeta'));
isvalid = false;
}
if(!isValid(firstname)){
ApexPages.addmessage(new ApexPages.message(ApexPages.severity.Error, '
Falta el Campo Obligatorio: Nombre(s)'));
isvalid = false;
}
if(!isValid(lastname)){
ApexPages.addmessage(new ApexPages.message(ApexPages.severity.Error, '
Falta el Campo Obligatorio: Apellido(s)'));
isvalid = false;
}
if(!isValid(address)){
ApexPages.addmessage(new ApexPages.message(ApexPages.severity.Error, '
Falta el Campo Obligatorio: Dirección'));
isvalid = false;
}
if(!isValid(state)){
ApexPages.addmessage(new ApexPages.message(ApexPages.severity.Error, '
Falta el Campo Obligatorio: Estado'));
isvalid = false;
}
if(!isValid(zip)){
ApexPages.addmessage(new ApexPages.message(ApexPages.severity.Error, '
Falta el Campo Obligatorio: Código Postal'));
isvalid = false;
}

return isvalid;

private boolean isValid(string val){


return val == null ? false : val.trim().length() == 0 ? false: true;
}
}

35
~ ForgotPasswordController

/**
* An apex page controller that exposes the site forgot password functionality
*/
public with sharing class ForgotPasswordController {
public String username {get; set;}

public ForgotPasswordController() {}

public PageReference forgotPassword() {


boolean success = Site.forgotPassword(username);
PageReference pr = Page.ForgotPasswordConfirm;
pr.setRedirect(true);

if (success) {
return pr;
}
return null;
}
}

~ ForgotPasswordControllerTest

/**
* An apex page controller that exposes the site forgot password functionality
*/
@IsTest public with sharing class ForgotPasswordControllerTest {
@IsTest(SeeAllData=true) public static void testForgotPasswordController() {
// Instantiate a new controller with all parameters in the page
ForgotPasswordController controller = new ForgotPasswordController();
controller.username = 'test@salesforce.com';

System.assertEquals(controller.forgotPassword(),null);
}
}

~ MyProfilePageController
/**
* An apex class that updates portal user details.
Guest users are never able to access this page.
*/
public with sharing class MyProfilePageController {

private User user;


private boolean isEdit = false;

36
public User getUser() {
return user;
}

public MyProfilePageController() {
user = [SELECT id, email, username, usertype, communitynickname, timezonesidk
ey, languagelocalekey, firstname, lastname, phone, title,
street, city, country, postalcode, state, localesidkey, mobilephone, extension, f
ax, contact.email
FROM User
WHERE id = :UserInfo.getUserId()];
// guest users should never be able to access this page
if (user.usertype == 'GUEST') {
throw new NoAccessException();
}
}

public Boolean getIsEdit() {


return isEdit;
}

public void edit() {


isEdit=true;
}

public void save() {


try {
update user;
isEdit=false;
} catch(DmlException e) {
ApexPages.addMessages(e);
}
}

public PageReference changePassword() {


return Page.ChangePassword;
}

public void cancel() {


isEdit=false;
user = [SELECT id, email, username, communitynickname, timezonesidkey, langu
agelocalekey, firstname, lastname, phone, title,
street, city, country, postalcode, state, localesidkey, mobilephone, extension, f
ax, contact.email
FROM User

37
WHERE id = :UserInfo.getUserId()];
}
}

~ MyProfilePageControllerTest
/**
* An apex class that updates details of a portal user.
Guest users are never able to access this page.
*/
@IsTest public with sharing class MyProfilePageControllerTest {

@IsTest(SeeAllData=true) static void testSave() {


// Modify the test to query for a portal user that exists in your org
List<User> existingPortalUsers = [SELECT id, profileId, userRoleId FROM User W
HERE UserRoleId <> null AND UserType='CustomerSuccess'];

if (existingPortalUsers.isEmpty()) {
User currentUser = [select id, title, firstname, lastname, email, phone, mobilepho
ne, fax, street, city, state, postalcode, country
FROM User WHERE id =: UserInfo.getUserId()];
MyProfilePageController controller = new MyProfilePageController();
System.assertEquals(currentUser.Id, controller.getUser().Id, 'Did not successfull
y load the current user');
System.assert(controller.getIsEdit() == false, 'isEdit should default to false');
controller.edit();
System.assert(controller.getIsEdit() == true);
controller.cancel();
System.assert(controller.getIsEdit() == false);

System.assert(Page.ChangePassword.getUrl().equals(controller.changePasswo
rd().getUrl()));

String randFax = Math.rint(Math.random() * 1000) + '5551234';


controller.getUser().Fax = randFax;
controller.save();
System.assert(controller.getIsEdit() == false);

currentUser = [Select id, fax from User where id =: currentUser.Id];


System.assert(currentUser.fax == randFax);
} else {
User existingPortalUser = existingPortalUsers[0];
String randFax = Math.rint(Math.random() * 1000) + '5551234';

System.runAs(existingPortalUser) {
MyProfilePageController controller = new MyProfilePageController();

38
System.assertEquals(existingPortalUser.Id, controller.getUser().Id, 'Did not su
ccessfully load the current user');
System.assert(controller.getIsEdit() == false, 'isEdit should default to false');
controller.edit();
System.assert(controller.getIsEdit() == true);

controller.cancel();
System.assert(controller.getIsEdit() == false);

controller.getUser().Fax = randFax;
controller.save();
System.assert(controller.getIsEdit() == false);
}

// verify that the user was updated


existingPortalUser = [Select id, fax from User where id =: existingPortalUser.Id];
System.assert(existingPortalUser.fax == randFax);
}
}
}

~ ProductController

public with sharing class ProductController {

public List<Product2> productList {get; set;}


//id del producto seleccionado(ver detalles)
//public Id idOpp {get; set;}
public Product2 producto {get; set;}
public Opportunity carrito {get; set;}
public OpportunityLineItem oli {get; set;}
//lista de precios estandar
public PriceBook2 pb2Standard {get; set;}
public PriceBookEntry pbe {get; set;}

public String cart {get; set;}

public ProductController(ApexPages.StandardController stdController) {


producto = [SELECT Id, Name, Description, Categoria__c, Marca__c,ImgId__c
FROM Product2
WHERE Id =: stdController.getId()];

pb2Standard = [select Id from Pricebook2 where isStandard=true];

pbe = [SELECT Id, UnitPrice FROM PriceBookEntry WHERE Pricebook2.id =:pb2Sta

39
ndard.id AND Product2.id =: producto.id];

cart = apexpages.currentpage().getparameters().get('cart');

//landing y redirect eran de prueba para hacerlo con button html


public void landing(){

public PageReference redirect(){


PageReference page = new PageReference('/home');
page.setRedirect(true);
return page;
}

public PageReference agregar(){


if(producto!=NULL){
if(cart==''|| cart == NULL){ //si no hay un carrito crea uno nuevo y lo regresa
carrito = new Opportunity();
carrito.Name = 'carrito de compras con '+producto.Name;
carrito.CloseDate = System.today();
carrito.StageName = 'Prospecting';
carrito.Description = 'Posible compra en el sitio (falta que el cliente realize su pago y
confirme la compra)';
insert carrito;

//idOpp = carrito.Id;

oli = new OpportunityLineItem();


oli.Quantity = 1;
oli.Description = 'Comprado en la tienda en línea';
oli.ServiceDate = System.today();
oli.OpportunityId = carrito.Id;
oli.UnitPrice = pbe.UnitPrice;
oli.PriceBookEntryId = pbe.Id;

insert oli;

//Utility.cart =carrito.id;
PageReference page = new PageReference('/home?cart='+carrito.id);
page.setRedirect(true);
return page;
}

40
else{//si si hay carrito solo lo añadimos
carrito = [SELECT Id,Name,CloseDate,StageName,Description FROM Opportunit
y WHERE id=:cart];
carrito.Name = 'carrito de compras con '+producto.Name;
carrito.CloseDate = System.today();
carrito.StageName = 'Prospecting';
carrito.Description = 'Posible compra en el sitio (falta que el cliente realize su pago y
confirme la compra)';
update carrito;

//idOpp = carrito.Id;

oli = new OpportunityLineItem();


oli.Quantity = 1;
oli.Description = 'Comprado en la tienda en línea';
oli.ServiceDate = System.today();
oli.OpportunityId = carrito.Id;
oli.UnitPrice = pbe.UnitPrice;
oli.PriceBookEntryId = pbe.Id;

insert oli;

//Utility.cart =carrito.id;
PageReference page = new PageReference('/home?cart='+carrito.id);
page.setRedirect(true);
return page;
}
}

PageReference page = new PageReference('/home?cart='+carrito.id);


page.setRedirect(true);
//idOpp = carrito.Id;
return page;
}

public PageReference checar(){


if(cart==''|| cart == NULL){ //si no hay un carrito creo uno y lo checa

carrito = new Opportunity();


carrito.Name = 'carrito de compras con '+producto.Name;
carrito.CloseDate = System.today();
carrito.StageName = 'Prospecting';
carrito.Description = 'Compra en el sitio';
insert carrito;

41
//idOpp = carrito.Id;

oli = new OpportunityLineItem();


oli.Quantity = 1;
oli.Description = 'Comprado en la tienda en línea';
oli.ServiceDate = System.today();
oli.OpportunityId = carrito.Id;
oli.UnitPrice = pbe.UnitPrice;
oli.PriceBookEntryId = pbe.Id;

insert oli;

//Utility.cart =carrito.id;
PageReference page = new PageReference('/ShoppingCart?id='+carrito.Id);
page.setRedirect(true);
update carrito;
return page;
} else{
carrito = [SELECT Id,Name,CloseDate,StageName,Description FROM Opportunit
y WHERE id=:cart];
carrito.Name = 'carrito de compras con '+producto.Name;
carrito.CloseDate = System.today();
carrito.StageName = 'Prospecting';
carrito.Description = 'Compra en el sitio';
update carrito;

//idOpp = carrito.Id;

oli = new OpportunityLineItem();


oli.Quantity = 1;
oli.Description = 'Comprado en la tienda en línea';
oli.ServiceDate = System.today();
oli.OpportunityId = carrito.Id;
oli.UnitPrice = pbe.UnitPrice;
oli.PriceBookEntryId = pbe.Id;

insert oli;

//Utility.cart =carrito.id;
PageReference page = new PageReference('/ShoppingCart?id='+carrito.Id);
page.setRedirect(true);
update carrito;
return page;
}
}

42
}

~ ProductTriggerHandler

public with sharing class ProductTriggerHandler {


public ProductTriggerHandler() {

}
}

-ProductTriggerHelper
public class ProductTriggerHelper {
/*public static void Helper(List<Product2> newList){

list<Id> Idlist = new list<Id>();


list<product2> ProdsToUpdate = new list<Product2>();

//productos que activaron el trigger


for(Product2 pr:newList){
Idlist.add(pr.Id);
}
//traemos el precio estandar y su id
pricebook2 pb = [select Id from pricebook2 where IsStandard = TRUE][0];
Id stPrId = pb.Id;

//si el producto tiene un precio estandar lo asignamos al campo


for(product2 p:[select Product_Price_Unit__c,Id from product2 where Id IN :Idlist]){
for(pricebookentry pbe:[select Product2Id,UnitPrice from pricebookentry where pric
ebook2Id = :stPrId and product2Id IN :Idlist]){
If((pbe.Product2Id == p.Id)&&(p.Product_Price_Unit__c!=pbe.UnitPrice)){
p.Product_Price_Unit__c = pbe.UnitPrice;
system.debug('this is it '+pbe.UnitPrice);
system.debug('this is that '+p.Product_Price_Unit__c);
ProdsToUpdate.add(p);
}
}
}

//Si hay productos para actualizar los actualiza


If(ProdsToUpdate.size()>0&&trigger.isafter){
update ProdsToUpdate;
}

43
}*/
}
- SiteLoginController
/**
* An apex page controller that exposes the site login functionality
*/
global with sharing class SiteLoginController {
global String username {get; set;}
global String password {get; set;}

global PageReference login() {


String startUrl = System.currentPageReference().getParameters().get('startURL');
return Site.login(username, password, startUrl);
}

global SiteLoginController () {}
}

~ SiteLoginControllerTest
/**
* An apex page controller that exposes the site login functionality
*/
@IsTest global with sharing class SiteLoginControllerTest {
@IsTest(SeeAllData=true) global static void testSiteLoginController () {
// Instantiate a new controller with all parameters in the page
SiteLoginController controller = new SiteLoginController ();
controller.username = 'test@salesforce.com';
controller.password = '123456';

System.assertEquals(controller.login(),null);
}
}

- SiteRegisterController
/**
* An apex class that creates a portal user
*/
public with sharing class SiteRegisterController {
// PORTAL_ACCOUNT_ID is the account on which the contact will be created on and
then enabled as a portal user.
// you need to add the account owner into the role hierarchy before this will work - ple
ase see Customer Portal Setup help for more information.
private static Id PORTAL_ACCOUNT_ID = '001x000xxx35tPN';

public SiteRegisterController () {

44
}

public String username {get; set;}


public String email {get; set;}
public String password {get; set {password = value == null ? value : value.trim(); } }
public String confirmPassword {get; set { confirmPassword = value == null ? value : v
alue.trim(); } }
public String communityNickname {get; set { communityNickname = value == null ? v
alue : value.trim(); } }

private boolean isValidPassword() {


return password == confirmPassword;
}

public PageReference registerUser() {


// it's okay if password is null - we'll send the user a random password in that case
if (!isValidPassword()) {
ApexPages.Message msg = new ApexPages.Message(ApexPages.Severity.ERR
OR, Label.site.passwords_dont_match);
ApexPages.addMessage(msg);
return null;
}
User u = new User();
u.Username = username;
u.Email = email;
u.CommunityNickname = communityNickname;

String accountId = PORTAL_ACCOUNT_ID;

// lastName is a required field on user, but if it isn't specified, we'll default it to the u
sername
String userId = Site.createPortalUser(u, accountId, password);
if (userId != null) {
if (password != null && password.length() > 1) {
return Site.login(username, password, null);
}
else {
PageReference page = System.Page.SiteRegisterConfirm;
page.setRedirect(true);
return page;
}
}
return null;
}
}

45
~ SiteRegisterControllerTest
/**
* Class containing tests for SiteRegisterController
*/
@IsTest public with sharing class SiteRegisterControllerTest {
@IsTest(SeeAllData=true) static void testRegistration() {
SiteRegisterController controller = new SiteRegisterController();
controller.username = 'test@force.com';
controller.email = 'test@force.com';
controller.communityNickname = 'test';
// registerUser will always return null when the page isn't accessed as a guest user
System.assert(controller.registerUser() == null);

controller.password = 'abcd1234';
controller.confirmPassword = 'abcd123';
System.assert(controller.registerUser() == null);
}
}

~ TestAuthorizeDotNetLib

description : the class is use to coverage the test for available classes. The code is jus
t to cover the
code coverage (left actual testing due to time limit) , however it can be written
in good way using asserts.
*/
public class TestAuthorizeDotNetLib{
@isTest
private static void testclasses(){
DoPaymentHandler doPayment = new DoPaymentHandler();
doPayment.process();
doPayment.getMonths();
doPayment.getYears();
doPayment.amount='test';
doPayment.firstname='test';
doPayment.lastname='test';
doPayment.email='test';
doPayment.address='test';
doPayment.city='test';
doPayment.state='test';
doPayment.zip='test';
doPayment.cardholder='test';
doPayment.cardnumber='test';
doPayment.cardyear='test';
doPayment.cardmonth='test';

46
doPayment.cardcvv='test';
doPayment.expiration='test';
doPayment.selectedCardType='test';
doPayment.process();
}

~ Utility
public class Utility {

public static String cart;

~ VerificarRecursividad

public class VerificarRecursividad {

private static boolean ejecucion = true;

public static boolean EjecutarUnaVez(){

if(ejecucion){

ejecucion = false;
return true;
}
else{

return ejecucion;
}
}
}

Visual Force

-ShoppingCart

<apex:page showHeader="false" sidebar="false" standardStylesheets="false"


standardController="Opportunity" extensions="CheckoutController">
<!--cambie a cartcontroller porque productcontroller pide un id y marca error..-->
<apex:form id="contenido">
<html lang="en">
<head>
<meta charset="utf-8"/>

47
<meta http-equiv="X-UA-Compatible" content="IE=edge"/>
<meta name="viewport" content="width=device-width, initial-scale=1"/>
<!-- The above 3 meta tags *must* come first in the head; any other head
content must come *after* these tags -->
<meta name="description" content=""/>
<meta name="author" content=""/>
<link rel="icon" href="{!URLFOR($Resource.bootstrap, 'bootstrap-
3.3.7/docs/favicon.ico')}"/>

<title>CompuSoluciones: Carrito de Compras </title>

<!-- Bootstrap core CSS -->


<link href="{!URLFOR($Resource.bootstrap, 'bootstrap-
3.3.7/dist/css/bootstrap.min.css')}" rel="stylesheet"/>

<!-- IE10 viewport hack for Surface/desktop Windows 8 bug -->


<link href="{!URLFOR($Resource.bootstrap, 'bootstrap-3.3.7/assets/css/ie10-
viewport-bug-workaround.css')}" rel="stylesheet"/>

<!-- Just for debugging purposes. Don't actually copy these 2 lines! -->
<!--[if lt IE 9]><script src="../../assets/js/ie8-responsive-file-
warning.js"></script><![endif]-->
<script src="{!URLFOR($Resource.bootstrap, 'bootstrap-3.3.7/assets/js/ie-
emulation-modes-warning.js')}"></script>

<!-- HTML5 shim and Respond.js for IE8 support of HTML5 elements and
media queries -->
<!--[if lt IE 9]>
<script
src="https://oss.maxcdn.com/html5shiv/3.7.3/html5shiv.min.js"></script>
<script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script>
<![endif]-->

<!-- Custom styles for this template -->


<link href="{!URLFOR($Resource.carrusel)}" rel="stylesheet"/>

</head>

<!-- NAVBAR
================================================== -->
<body>
<div class="navbar-wrapper">
<div class="container">
<nav class="navbar navbar-inverse navbar-static-top">

48
<div class="container">
<div class="navbar-header" style="background: url({!
$Resource.logocompu}); background-size: 400px 100px; background-position: center
top; background-repeat: no-repeat">
<button type="button" class="navbar-toggle collapsed" data-
toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<!-- <img src="{!URLFOR($Resource.logocompu)}" width="350"
height="90" align="center" alt="logo" />-->
<a class="navbar-brand" href="#"> CompuSoluciones</a>
</div>
<div id="navbar" class="navbar-collapse collapse">
<!-- <ul class="nav navbar-nav">
<li class="active"><a href="/home?cart={!venta.id}">Inicio</a></li>
<li><a href="/Contacto?cart={!venta.id}">Contacto</a></li>
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown"
role="button" aria-haspopup="true" aria-expanded="false">Categorías <span
class="caret"></span></a>
<ul class="dropdown-menu">
<li><a href="/home?cat=Almacenamiento&cart={!
venta.id}">Almacenamiento</a></li>
<li><a href="/home?cat=Computadoras&cart={!
venta.id}">Computadoras</a></li>
<li><a href="/home?cat=Gabinetes&cart={!venta.id}">Gabinetes</a></li>
<li><a href="/home?cat=Kits Teclado y Mouse&cart={!venta.id}">Kits
Teclado y Mouse</a></li>
<li><a href="/home?cat=Memorias RAM&cart={!venta.id}">Memorias
RAM</a></li>
<li><a href="/home?cat=Procesadores&cart={!
venta.id}">Procesadores</a></li>
<li><a href="/home?cat=Software&cart={!venta.id}">Software</a></li>
<li><a href="/home?cat=Tarjetas Madre&cart={!venta.id}">Tarjetas
Madre</a></li>
<li role="separator" class="divider"></li>
<li class="dropdown-header">Paquetes</li>
<li><a href="/home?cat=Computadoras&paq=si&cart={!
venta.id}">Computadoras</a></li>
</ul>
</li>
</ul>-->
<ul class="nav navbar-nav navbar-right">

49
<!--no enfocarse mejor hacer integracion con salesforce-->

</ul>
</div>
</div>
</nav>
</div>
</div>

<div class="container marketing">

<div class="page-header">
<br/><br/>
<h1>Carrito de compras</h1>
</div>

<link href="//maxcdn.bootstrapcdn.com/font-awesome/4.1.0/css/font-awesome.min.css"
rel="stylesheet"/>
<div class="container">
<apex:inputHidden id="success" />
<apex:actionFunction name="seguirComprando" action="{!seguirComprando}"
reRender="success" />
<apex:actionFunction name="proceder" action="{!proceder}" reRender="success" />
<table id="cart" class="table table-hover table-condensed">
<thead>
<tr>
<th style="width:50%">Producto</th>
<th style="width:10%">Precio</th>
<th style="width:8%">Cantidad</th>
<th style="width:22%" class="text-
center">Subtotal</th>
<th style="width:10%"></th>
</tr>
</thead>
<tbody>

<apex:repeat value="{!productos}" var="producto" >


<tr>
<td data-th="Product">

50
<div class="row">
<div class="col-sm-2
hidden-xs"><img src="/servlet/servlet.FileDownload?file={!producto.product2.ImgId__c}"
alt="{!producto.product2.Name}" class="img-responsive" width="140" height="140"
style="margin: 0 auto;"/></div>
<div class="col-sm-10">
<h4
class="nomargin">{!producto.product2.Name}</h4>
<p>{!
producto.product2.Description}</p>
</div>
</div>
</td>
<td data-th="Price">${!
producto.Listprice}</td>
<td data-th="Quantity">
<!--<apex:inputField value="{!
producto.Quantity}"/>-->
<input class="form-control text-
center" value="{!producto.Quantity}" readonly="true" />
<!--<div><apex:inputText value="{!
producto.Quantity}" html-placeholder="{!producto.Quantity}" styleClass="form-control"
/></div>-->

</td>
<td data-th="Subtotal" class="text-
center">${!producto.TotalPrice}</td>
<td class="actions" data-th="">
<!--<button class="btn btn-info btn-
sm" onclick="refrescar();" ><i class="fa fa-refresh"></i></button>-->
<apex:commandButton value="+"
styleClass="btn btn-info btn-sm" action="{!aumentar}" rerender="contenido">
<apex:param
name="contIdParam" value="{!producto.Id}" assignTo="{!oliIdChosen}"/>
</apex:commandButton>
&nbsp;
<apex:commandButton value="-"
styleClass="btn btn-primary btn-sm" action="{!restar}" rerender="contenido">
<apex:param
name="contIdParam" value="{!producto.Id}" assignTo="{!oliIdChosen}"/>
</apex:commandButton>
&nbsp;
<apex:commandButton
value="Eliminar" styleClass="btn btn-danger btn-sm" action="{!eliminar}"
rerender="contenido">

51
<apex:param
name="contIdParam" value="{!producto.Id}" assignTo="{!oliIdChosen}"/>
</apex:commandButton>

</td>
</tr>
</apex:repeat>
</tbody>
<tfoot>
<tr class="visible-xs">
<td class="text-center"><strong>Total ${!
venta.Amount}</strong></td>
</tr>
<tr>
<td><a class="btn btn-warning"
onclick="seguirComprando();"><i class="fa fa-angle-left"></i> <span class="glyphicon
glyphicon-shopping-cart"></span>Seguir Comprando</a></td>
<td colspan="2" class="hidden-xs"></td>
<td class="hidden-xs text-
center"><strong>Total ${!venta.Amount}</strong></td>
<td><a href="#" class="btn btn-success
btn-block" onclick="proceder();"><span class="glyphicon glyphicon-ok"></span>
Proceder al pago <i class="fa fa-angle-right"></i></a></td>
</tr>
</tfoot>
</table>
</div>

<hr class="featurette-divider"/>

<!-- FOOTER -->


<footer>
<p class="pull-right"><a href="#">Regresar al inicio</a></p>
<p>&copy; 2017, CompuSoluciones, SA de CV. Todos los derechos
reservados.
&middot; <a href="/Contacto?cart={!venta.id}">Contáctanos</a> &middot; </p>
</footer>

</div><!-- /.container -->

<!-- Bootstrap core JavaScript

52
================================================== -->
<!-- Placed at the end of the document so the pages load faster -->
<script
src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
<!--Linea original-->
<!--<script>window.jQuery || document.write('<script
src="../../assets/js/vendor/jquery.min.js"><\/script>')</script>-->
<!--Linea modificada marca error sintaxis-->
<!--<script>window.jQuery || document.write('<script src="{!
URLFOR($Resource.bootstrap, \'bootstrap-
3.3.7/docs/assets/js/vendor/jquery.min.js\')}"><\/script>')</script>-->
<!--Nose si esta sirviendo?-->
<script>if(!window.jQuery) {
var script = document.createElement("script");
script.src ="{!URLFOR($Resource.bootstrap, 'bootstrap-
3.3.7/docs/assets/js/vendor/jquery.min.js')}";
document.body.appendChild(script);
}</script>
<script src="{!URLFOR($Resource.bootstrap, 'bootstrap-
3.3.7/dist/js/bootstrap.min.js')}"></script>
<!-- Just to make our placeholder images work. Don't actually copy the next
line! -->
<script src="{!URLFOR($Resource.bootstrap, 'bootstrap-
3.3.7/docs/assets/js/vendor/holder.min.js')}"></script>
<!-- IE10 viewport hack for Surface/desktop Windows 8 bug -->
<script src="{!URLFOR($Resource.bootstrap, 'bootstrap-
3.3.7/docs/assets/js/ie10-viewport-bug-workaround.js')}"></script>
</body>

</html>

</apex:form>
</apex:page>

- Checkout

<apex:page showHeader="false" sidebar="false" standardStylesheets="false"


standardController="Opportunity"
extensions="CheckoutController,DoPaymentHandler">
<!--cambie a cartcontroller porque productcontroller pide un id y marca error..-->
<apex:form id="contenido">
<html lang="en">
<head>
<meta charset="utf-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=edge"/>

53
<meta name="viewport" content="width=device-width, initial-scale=1"/>
<!-- The above 3 meta tags *must* come first in the head; any other head
content must come *after* these tags -->
<meta name="description" content=""/>
<meta name="author" content=""/>
<link rel="icon" href="{!URLFOR($Resource.bootstrap, 'bootstrap-
3.3.7/docs/favicon.ico')}"/>

<title>CompuSoluciones: Completar la compra </title>

<!-- Bootstrap core CSS -->


<link href="{!URLFOR($Resource.bootstrap, 'bootstrap-
3.3.7/dist/css/bootstrap.min.css')}" rel="stylesheet"/>

<!-- IE10 viewport hack for Surface/desktop Windows 8 bug -->


<link href="{!URLFOR($Resource.bootstrap, 'bootstrap-3.3.7/assets/css/ie10-
viewport-bug-workaround.css')}" rel="stylesheet"/>

<!-- Just for debugging purposes. Don't actually copy these 2 lines! -->
<!--[if lt IE 9]><script src="../../assets/js/ie8-responsive-file-
warning.js"></script><![endif]-->
<script src="{!URLFOR($Resource.bootstrap, 'bootstrap-3.3.7/assets/js/ie-
emulation-modes-warning.js')}"></script>

<!-- HTML5 shim and Respond.js for IE8 support of HTML5 elements and
media queries -->
<!--[if lt IE 9]>
<script
src="https://oss.maxcdn.com/html5shiv/3.7.3/html5shiv.min.js"></script>
<script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script>
<![endif]-->

<!-- Custom styles for this template -->


<link href="{!URLFOR($Resource.carrusel)}" rel="stylesheet"/>

</head>

<!-- NAVBAR
================================================== -->
<body>
<div class="navbar-wrapper">
<div class="container">
<nav class="navbar navbar-inverse navbar-static-top">
<div class="container">

54
<div class="navbar-header" style="background:
url(https://c.na59.visual.force.com/resource/1502465258000/logocompu); background-
size: 400px 100px; background-position: center top; background-repeat: no-repeat">
<button type="button" class="navbar-toggle collapsed" data-
toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<!-- <img src="{!URLFOR($Resource.logocompu)}" width="350"
height="90" align="center" alt="logo" />-->
<a class="navbar-brand" href="#"> CompuSoluciones</a>
</div>
<div id="navbar" class="navbar-collapse collapse">
<ul class="nav navbar-nav">
<li class="active"><a href="/home">Inicio</a></li>
<!--<li><a href="/Contacto?cart={!venta.id}">Contacto</a></li>
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown"
role="button" aria-haspopup="true" aria-expanded="false">Categorías <span
class="caret"></span></a>
<ul class="dropdown-menu">
<li><a href="/home?cat=Almacenamiento&cart={!
venta.id}">Almacenamiento</a></li>
<li><a href="/home?cat=Computadoras&cart={!
venta.id}">Computadoras</a></li>
<li><a href="/home?cat=Gabinetes&cart={!venta.id}">Gabinetes</a></li>
<li><a href="/home?cat=Kits Teclado y Mouse&cart={!venta.id}">Kits
Teclado y Mouse</a></li>
<li><a href="/home?cat=Memorias RAM&cart={!venta.id}">Memorias
RAM</a></li>
<li><a href="/home?cat=Procesadores&cart={!
venta.id}">Procesadores</a></li>
<li><a href="/home?cat=Software&cart={!venta.id}">Software</a></li>
<li><a href="/home?cat=Tarjetas Madre&cart={!venta.id}">Tarjetas
Madre</a></li>
<li role="separator" class="divider"></li>
<li class="dropdown-header">Paquetes</li>
<li><a href="/home?cat=Computadoras&paq=si&cart={!
venta.id}">Computadoras</a></li>
</ul>
</li>-->
</ul>
<ul class="nav navbar-nav navbar-right">
<!--no enfocarse mejor hacer integracion con salesforce-->

55
</ul>
</div>
</div>
</nav>
</div>
</div>

<div class="container marketing">

<div class="page-header">
<br/><br/>
<h2>Favor de ingresar sus datos</h2>
</div>

<apex:pageBlock title="Información del Pago" mode="edit" >


<apex:pagemessages ></apex:pagemessages>
<apex:pageBlockSection columns="1" rendered="{!NOT(isSuccess)}">
<div class="form-group"><apex:pageBlockSectionItem >
<apex:outputLabel value="Total a pagar"></apex:outputLabel>
<apex:outputText value="{!amount}" id="amount"/>
</apex:pageBlockSectionItem></div>
<apex:pageBlockSectionItem rendered="false" >
<apex:outputLabel value="Total a pagar"></apex:outputLabel>
<apex:outputText value="{!venta.Amount}" styleClass="form-control" >
<apex:param assignTo="{!amount}" value="{!venta.Amount}" id="amount2" />
</apex:outputText>
</apex:pageBlockSectionItem>

<div class="form-group"><apex:pageBlockSectionItem >


<apex:outputLabel value="Nombre(s)"></apex:outputLabel>
<apex:inputText value="{!firstname}" styleClass="form-control"/>
</apex:pageBlockSectionItem></div>
<div class="form-group"><apex:pageBlockSectionItem >
<apex:outputLabel value="Apellido(s)"></apex:outputLabel>
<apex:inputText value="{!lastname}" styleClass="form-control"/>
</apex:pageBlockSectionItem></div>
<div class="form-group"><apex:pageBlockSectionItem >
<apex:outputLabel value="Email"></apex:outputLabel>
<apex:inputText value="{!email}" styleClass="form-control"/>
</apex:pageBlockSectionItem></div>

56
<div class="form-group"><apex:pageBlockSectionItem >
<apex:outputLabel value="Dirección"></apex:outputLabel>
<apex:inputText value="{!address}" styleClass="form-control"/>
</apex:pageBlockSectionItem></div>
<div class="form-group"><apex:pageBlockSectionItem >
<apex:outputLabel value="Ciudad"></apex:outputLabel>
<apex:inputText value="{!city}" styleClass="form-control"/>
</apex:pageBlockSectionItem></div>
<div class="form-group"><apex:pageBlockSectionItem >
<apex:outputLabel value="Estado"></apex:outputLabel>
<apex:inputText value="{!state}" styleClass="form-control"/>
</apex:pageBlockSectionItem></div>
<div class="form-group"><apex:pageBlockSectionItem >
<apex:outputLabel value="Código Postal"></apex:outputLabel>
<apex:inputText value="{!zip}" styleClass="form-control"/>
</apex:pageBlockSectionItem></div>
<div class="form-group">
<br/>
<div class="col-md-12">
<span>Paga de manera segura usando tu tarjeta.</span>
</div>
<div class="col-md-12">
<ul class="cards">
<li class="visa hand">Visa</li>
<li class="mastercard hand">MasterCard</li>
<li class="amex hand">Amex</li>
</ul>
<div class="clearfix"></div>
</div>
</div>

<div class="form-group"><apex:pageBlockSectionItem >


<apex:outputLabel value="Tipo de Tarjeta"></apex:outputLabel>
<apex:selectList value="{!selectedCardType}" size="1" styleClass="btn btn-
secondary dropdown-toggle ">
<apex:selectOptions value="{!cardTypes}" />
</apex:selectList>
</apex:pageBlockSectionItem></div>
<div class="form-group"><apex:pageBlockSectionItem >
<apex:outputLabel value="Nombre(en la tarjeta)"></apex:outputLabel>
<apex:inputText value="{!cardholder}" styleClass="form-control"/>
</apex:pageBlockSectionItem></div>
<div class="form-group"><apex:pageBlockSectionItem >
<apex:outputLabel value="Número de tarjeta"></apex:outputLabel>
<apex:inputText value="{!cardnumber}" styleClass="form-control"/>
</apex:pageBlockSectionItem></div>

57
<div class="form-group"><apex:pageBlockSectionItem >
<apex:outputLabel value="Fecha de Expiración"></apex:outputLabel>
<apex:outputPanel >
<apex:selectList value="{!cardmonth}" size="1" styleClass="btn btn-
secondary dropdown-toggle">
<apex:selectOptions value="{!months}" />
</apex:selectList>
<apex:selectList value="{!cardyear}" size="1" styleClass="btn btn-
secondary dropdown-toggle">
<apex:selectOptions value="{!years}" />
</apex:selectList>
</apex:outputPanel>
</apex:pageBlockSectionItem></div>
<div class="form-group"><apex:pageBlockSectionItem >
<apex:outputLabel value="Código de tarjeta"></apex:outputLabel>
<apex:inputText value="{!cardcvv}" html-placeholder="Código de 3 dígitos"
styleClass="form-control"/>
</apex:pageBlockSectionItem></div>
<br/>

<apex:outputLabel value=""></apex:outputLabel>
<apex:pageBlockSectionItem >
<apex:commandButton value="Seguir Comprando"
onclick="window.location.href='/home?cart={!venta.id}'; return false;" styleClass="btn
btn-warning"/>
<apex:commandButton value="Pagar" action="{!process}" styleClass="btn
btn-success"/>
</apex:pageBlockSectionItem>

</apex:pageBlockSection>

</apex:pageBlock>

<!--<p><a class="btn btn-success" role="button">Pagar &raquo;</a></p>-->

<hr class="featurette-divider"/>

<!-- FOOTER -->


<footer>
<p class="pull-right"><a href="#">Regresar al inicio</a></p>
<p>&copy; 2017, CompuSoluciones, SA de CV. Todos los derechos
reservados.
&middot; <a href="/Contacto">Contáctanos</a> &middot; </p>
</footer>

58
</div><!-- /.container -->

<!-- Bootstrap core JavaScript


================================================== -->
<!-- Placed at the end of the document so the pages load faster -->
<script
src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
<!--Linea original-->
<!--<script>window.jQuery || document.write('<script
src="../../assets/js/vendor/jquery.min.js"><\/script>')</script>-->
<!--Linea modificada marca error sintaxis-->
<!--<script>window.jQuery || document.write('<script src="{!
URLFOR($Resource.bootstrap, \'bootstrap-
3.3.7/docs/assets/js/vendor/jquery.min.js\')}"><\/script>')</script>-->
<!--Nose si esta sirviendo?-->
<script>if(!window.jQuery) {
var script = document.createElement("script");
script.src ="{!URLFOR($Resource.bootstrap, 'bootstrap-
3.3.7/docs/assets/js/vendor/jquery.min.js')}";
document.body.appendChild(script);
}</script>
<script src="{!URLFOR($Resource.bootstrap, 'bootstrap-
3.3.7/dist/js/bootstrap.min.js')}"></script>
<!-- Just to make our placeholder images work. Don't actually copy the next
line! -->
<script src="{!URLFOR($Resource.bootstrap, 'bootstrap-
3.3.7/docs/assets/js/vendor/holder.min.js')}"></script>
<!-- IE10 viewport hack for Surface/desktop Windows 8 bug -->
<script src="{!URLFOR($Resource.bootstrap, 'bootstrap-
3.3.7/docs/assets/js/ie10-viewport-bug-workaround.js')}"></script>
</body>

</html>

</apex:form>
</apex:page>

-Home

<apex:page showHeader="false" sidebar="false" standardStylesheets="false"


standardController="Product2" extensions="CartController">

<html lang="en">
<head>

59
<meta charset="utf-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=edge"/>
<meta name="viewport" content="width=device-width, initial-scale=1"/>
<!-- The above 3 meta tags *must* come first in the head; any other head content
must come *after* these tags -->
<meta name="description" content=""/>
<meta name="author" content=""/>
<link rel="icon" href="{!URLFOR($Resource.bootstrap, 'bootstrap-
3.3.7/docs/favicon.ico')}"/>

<title>CompuSoluciones: Tienda en línea</title>

<!-- Bootstrap core CSS -->


<link href="{!URLFOR($Resource.bootstrap, 'bootstrap-
3.3.7/dist/css/bootstrap.min.css')}" rel="stylesheet"/>

<!-- IE10 viewport hack for Surface/desktop Windows 8 bug -->


<link href="{!URLFOR($Resource.bootstrap, 'bootstrap-3.3.7/assets/css/ie10-
viewport-bug-workaround.css')}" rel="stylesheet"/>

<!-- Just for debugging purposes. Don't actually copy these 2 lines! -->
<!--[if lt IE 9]><script src="../../assets/js/ie8-responsive-file-warning.js"></script><!
[endif]-->
<script src="{!URLFOR($Resource.bootstrap, 'bootstrap-3.3.7/assets/js/ie-emulation-
modes-warning.js')}"></script>

<!-- HTML5 shim and Respond.js for IE8 support of HTML5 elements and media
queries -->
<!--[if lt IE 9]>
<script src="https://oss.maxcdn.com/html5shiv/3.7.3/html5shiv.min.js"></script>
<script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script>
<![endif]-->

<!-- Custom styles for this template -->


<link href="{!URLFOR($Resource.carrusel)}" rel="stylesheet"/>

</head>

<!-- NAVBAR
================================================== -->
<body>
<div class="navbar-wrapper">
<div class="container">
<nav class="navbar navbar-inverse navbar-static-top">
<div class="container">

60
<div class="navbar-header" style="background: url({!$Resource.logocompu});
background-size: 400px 100px; background-position: center top; background-repeat:
no-repeat">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse"
data-target="#navbar" aria-expanded="false" aria-controls="navbar">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<!-- <img src="{!URLFOR($Resource.logocompu)}" width="350" height="90"
align="center" alt="logo" />-->
<a class="navbar-brand" href="#"> CompuSoluciones</a>
</div>
<div id="navbar" class="navbar-collapse collapse">
<ul class="nav navbar-nav">
<li class="active"><a href="/home?cart={!cart}">Inicio</a></li>
<li><a href="/Contacto?cart={!cart}">Contacto</a></li>
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button"
aria-haspopup="true" aria-expanded="false">Categorías <span
class="caret"></span></a>
<ul class="dropdown-menu">
<li><a href="?cat=Almacenamiento&cart={!cart}">Almacenamiento</a></li>
<li><a href="?cat=Computadoras&cart={!cart}">Computadoras</a></li>
<li><a href="?cat=Gabinetes&cart={!cart}">Gabinetes</a></li>
<li><a href="?cat=Kits Teclado y Mouse&cart={!cart}">Kits Teclado y
Mouse</a></li>
<li><a href="?cat=Memorias RAM&cart={!cart}">Memorias RAM</a></li>
<li><a href="?cat=Procesadores&cart={!cart}">Procesadores</a></li>
<li><a href="?cat=Software&cart={!cart}">Software</a></li>
<li><a href="?cat=Tarjetas Madre&cart={!cart}">Tarjetas Madre</a></li>
<li role="separator" class="divider"></li>
<li class="dropdown-header">Paquetes</li>
<li><a href="?cat=Computadoras&paq=si&cart={!
cart}">Computadoras</a></li>
</ul>
</li>
</ul>
<ul class="nav navbar-nav navbar-right">
<!--no enfocarse mejor hacer integracion con salesforce-->

<form class="navbar-form" role="search">


<div class="input-group">
<input type="text" class="form-control" placeholder="Buscar
producto" name="prod"/>

61
<div class="input-group-btn">
<button class="btn btn-default" type="submit"><i
class="glyphicon glyphicon-search"></i></button>
</div>
</div>
&nbsp; &nbsp;

<a class="btn btn-warning" onclick="aCarrito();"><span class="glyphicon


glyphicon-shopping-cart"></span> Carrito </a>
</form>
<apex:form >
<apex:inputHidden id="success" />
<apex:actionFunction name="aCarrito" action="{!aCarrito}"
reRender="success" />
</apex:form>
</ul>
</div>
</div>
</nav>
</div>
</div>

<!-- Carousel
================================================== -->
<div id="myCarousel" class="carousel slide" data-ride="carousel">
<!-- Indicators -->
<ol class="carousel-indicators">
<li data-target="#myCarousel" data-slide-to="0" class="active"></li>
<li data-target="#myCarousel" data-slide-to="1"></li>
<li data-target="#myCarousel" data-slide-to="2"></li>
</ol>
<div class="carousel-inner" role="listbox">
<div class="item active">
<img class="first-slide"
src="data:image/gif;base64,R0lGODlhAQABAIAAAHd3dwAAACH5BAAAAAAALAAAA
AABAAEAAAICRAEAOw==" alt="First slide"/>
<div class="container">
<div class="carousel-caption">
<h1>Computadoras</h1>
<p>Mira nuestras computadoras de gran calidad y a un precio muy bajo.</p>
<p><a class="btn btn-lg btn-primary" href="?cat=Computadoras&cart={!cart}"
role="button">Ver más</a></p>
</div>
</div>

62
</div>
<div class="item">
<img class="second-slide"
src="data:image/gif;base64,R0lGODlhAQABAIAAAHd3dwAAACH5BAAAAAAALAAAA
AABAAEAAAICRAEAOw==" alt="Second slide"/>
<div class="container">
<div class="carousel-caption">
<h1>Almacenamiento</h1>
<p>¡Todo lo que necesitas para guardar tu información!.</p>
<p><a class="btn btn-lg btn-primary" href="?cat=Almacenamiento&cart={!cart}"
role="button">Ver más</a></p>
</div>
</div>
</div>
<div class="item">
<img class="third-slide"
src="data:image/gif;base64,R0lGODlhAQABAIAAAHd3dwAAACH5BAAAAAAALAAAA
AABAAEAAAICRAEAOw==" alt="Third slide"/>
<div class="container">
<div class="carousel-caption">
<h1>Kits Teclado y Mouse</h1>
<p>¿Necesitas teclado y mouse?. ¡Da click aquí!</p>
<p><a class="btn btn-lg btn-primary" href="?cat=Kits Teclado y Mouse&cart={!
cart}" role="button">Ver más</a></p>
</div>
</div>
</div>
</div>
<a class="left carousel-control" href="#myCarousel" role="button" data-
slide="prev">
<span class="glyphicon glyphicon-chevron-left" aria-hidden="true"></span>
<span class="sr-only">Previous</span>
</a>
<a class="right carousel-control" href="#myCarousel" role="button" data-
slide="next">
<span class="glyphicon glyphicon-chevron-right" aria-hidden="true"></span>
<span class="sr-only">Next</span>
</a>
</div><!-- /.carousel -->

<!-- Marketing messaging and featurettes


================================================== -->
<!-- Wrap the rest of the page in another container to center all the content. -->

<div class="container marketing">

63
<!-- Three columns of text below the carousel -->

<!--original de SF<img src="/servlet/servlet.FileDownload?file=015f400000025M6"


alt="Imagen del producto" style="height:500px; width:500px;" border="0"/>-->
<div class="row">
<apex:repeat value="{!productList2}" var="producto" id="listadoproductos">

<div class="col-lg-4" >


<img class="img-responsive" src="/servlet/servlet.FileDownload?file={!
producto.ImgId__c}" alt="{!producto.Name}" width="140" height="140" style="margin: 0
auto;" />
<h2 align="center"><font color="firebrick">{!producto.Name} </font></h2>
<p align="justify" id="minimizar" >{!producto.Description}</p>
<p><a class="btn btn-success" href="/producto?id={!producto.id}&cart={!cart}"
role="button">Ver detalles &raquo;</a></p>
<br/>
</div>

</apex:repeat><!-- /.col-lg-4 -->


</div>
<!-- /.row -->

<!-- START THE FEATURETTES -->

<hr class="featurette-divider"/>

<div class="row featurette">


<div class="col-md-7">
<h2 class="featurette-heading">Discos de Estado Sólido <span class="text-
muted">¡Esperálos pronto!</span></h2>
<p class="lead"><br/>Deja atrás tu disco duro.<br/> Inicia Windows en instantes,
carga tus programas y juegos a una gran velocidad.</p>
</div>
<div class="col-md-5">
<img class="featurette-image img-responsive center-block" src="{!
$Resource.ssd}" alt="ssdvshdd"/>
</div>
</div>

<!--<hr class="featurette-divider"/>

<div class="row featurette">


<div class="col-md-7 col-md-push-5">

64
<h2 class="featurette-heading">Oh yeah, it's that good. <span class="text-
muted">See for yourself.</span></h2>
<p class="lead">Donec ullamcorper nulla non metus auctor fringilla. Vestibulum id
ligula porta felis euismod semper. Praesent commodo cursus magna, vel scelerisque
nisl consectetur. Fusce dapibus, tellus ac cursus commodo.</p>
</div>
<div class="col-md-5 col-md-pull-7">
<img class="featurette-image img-responsive center-block" data-
src="holder.js/500x500/auto" alt="Generic placeholder image"/>
</div>
</div>

<hr class="featurette-divider"/>

<div class="row featurette">


<div class="col-md-7">
<h2 class="featurette-heading">And lastly, this one. <span class="text-
muted">Checkmate.</span></h2>
<p class="lead">Donec ullamcorper nulla non metus auctor fringilla. Vestibulum id
ligula porta felis euismod semper. Praesent commodo cursus magna, vel scelerisque
nisl consectetur. Fusce dapibus, tellus ac cursus commodo.</p>
</div>
<div class="col-md-5">
<img class="featurette-image img-responsive center-block" data-
src="holder.js/500x500/auto" alt="Generic placeholder image"/>
</div>
</div>-->

<hr class="featurette-divider"/>

<!-- /END THE FEATURETTES -->

<!-- FOOTER -->


<footer>
<p class="pull-right"><a href="#">Regresar al inicio</a></p>
<p>&copy; 2017, CompuSoluciones, SA de CV. Todos los derechos reservados.
&middot; <a href="/Contacto?cart={!cart}">Contáctanos</a> &middot; </p>
</footer>

</div><!-- /.container -->

<!-- Bootstrap core JavaScript


================================================== -->
<!-- Placed at the end of the document so the pages load faster -->

65
<script
src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
<!--Linea original-->
<!--<script>window.jQuery || document.write('<script
src="../../assets/js/vendor/jquery.min.js"><\/script>')</script>-->
<!--Linea modificada marca error sintaxis-->
<!--<script>window.jQuery || document.write('<script src="{!
URLFOR($Resource.bootstrap, \'bootstrap-
3.3.7/docs/assets/js/vendor/jquery.min.js\')}"><\/script>')</script>-->
<!--Nose si esta sirviendo?-->
<script>if(!window.jQuery) {
var script = document.createElement("script");
script.src ="{!URLFOR($Resource.bootstrap, 'bootstrap-
3.3.7/docs/assets/js/vendor/jquery.min.js')}";
document.body.appendChild(script);
}</script>
<script src="{!URLFOR($Resource.bootstrap, 'bootstrap-
3.3.7/dist/js/bootstrap.min.js')}"></script>
<!-- Just to make our placeholder images work. Don't actually copy the next line! -->
<script src="{!URLFOR($Resource.bootstrap, 'bootstrap-
3.3.7/docs/assets/js/vendor/holder.min.js')}"></script>
<!-- IE10 viewport hack for Surface/desktop Windows 8 bug -->
<script src="{!URLFOR($Resource.bootstrap, 'bootstrap-3.3.7/docs/assets/js/ie10-
viewport-bug-workaround.js')}"></script>
</body>
</html>

</apex:page>

-Producto

<apex:page showHeader="false" sidebar="false" standardStylesheets="false"


standardController="Product2" extensions="CartController,ProductController">
<apex:form id="contenido">
<html lang="en">
<head>
<meta charset="utf-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=edge"/>
<meta name="viewport" content="width=device-width, initial-scale=1"/>
<!-- The above 3 meta tags *must* come first in the head; any other head
content must come *after* these tags -->
<meta name="description" content=""/>
<meta name="author" content=""/>
<link rel="icon" href="{!URLFOR($Resource.bootstrap, 'bootstrap-
3.3.7/docs/favicon.ico')}"/>

66
<title>CompuSoluciones: Detalle del producto {!producto.Name}</title>

<!-- Bootstrap core CSS -->


<link href="{!URLFOR($Resource.bootstrap, 'bootstrap-
3.3.7/dist/css/bootstrap.min.css')}" rel="stylesheet"/>

<!-- IE10 viewport hack for Surface/desktop Windows 8 bug -->


<link href="{!URLFOR($Resource.bootstrap, 'bootstrap-3.3.7/assets/css/ie10-
viewport-bug-workaround.css')}" rel="stylesheet"/>

<!-- Just for debugging purposes. Don't actually copy these 2 lines! -->
<!--[if lt IE 9]><script src="../../assets/js/ie8-responsive-file-
warning.js"></script><![endif]-->
<script src="{!URLFOR($Resource.bootstrap, 'bootstrap-3.3.7/assets/js/ie-
emulation-modes-warning.js')}"></script>

<!-- HTML5 shim and Respond.js for IE8 support of HTML5 elements and
media queries -->
<!--[if lt IE 9]>
<script
src="https://oss.maxcdn.com/html5shiv/3.7.3/html5shiv.min.js"></script>
<script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script>
<![endif]-->

<!-- Custom styles for this template -->


<link href="{!URLFOR($Resource.carrusel)}" rel="stylesheet"/>

</head>

<!-- NAVBAR
================================================== -->
<body>
<div class="navbar-wrapper">
<div class="container">
<nav class="navbar navbar-inverse navbar-static-top">
<div class="container">
<div class="navbar-header" style="background:
url(https://c.na59.visual.force.com/resource/1502465258000/logocompu); background-
size: 400px 100px; background-position: center top; background-repeat: no-repeat">
<button type="button" class="navbar-toggle collapsed" data-
toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>

67
<span class="icon-bar"></span>
</button>
<!-- <img src="{!URLFOR($Resource.logocompu)}" width="350"
height="90" align="center" alt="logo" />-->
<a class="navbar-brand" href="#"> CompuSoluciones</a>
</div>
<div id="navbar" class="navbar-collapse collapse">
<ul class="nav navbar-nav">
<li class="active"><a href="/home?cart={!cart}">Inicio</a></li>
<li><a href="/Contacto?cart={!cart}">Contacto</a></li>
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown"
role="button" aria-haspopup="true" aria-expanded="false">Categorías <span
class="caret"></span></a>
<ul class="dropdown-menu">
<li><a href="/home?cat=Almacenamiento&cart={!
cart}">Almacenamiento</a></li>
<li><a href="/home?cat=Computadoras&cart={!
cart}">Computadoras</a></li>
<li><a href="/home?cat=Gabinetes&cart={!cart}">Gabinetes</a></li>
<li><a href="/home?cat=Kits Teclado y Mouse&cart={!cart}">Kits Teclado y
Mouse</a></li>
<li><a href="/home?cat=Memorias RAM&cart={!cart}">Memorias
RAM</a></li>
<li><a href="/home?cat=Procesadores&cart={!
cart}">Procesadores</a></li>
<li><a href="/home?cat=Software&cart={!cart}">Software</a></li>
<li><a href="/home?cat=Tarjetas Madre&cart={!cart}">Tarjetas
Madre</a></li>
<li role="separator" class="divider"></li>
<li class="dropdown-header">Paquetes</li>
<li><a href="/home?cat=Computadoras&paq=si&cart={!
cart}">Computadoras</a></li>
</ul>
</li>
</ul>
<ul class="nav navbar-nav navbar-right">
<!--no enfocarse mejor hacer integracion con salesforce-->

</ul>
</div>
</div>
</nav>
</div>
</div>

68
<div class="container marketing">

<div class="page-header">
<br/><br/>
<h1><font color="firebrick">{!Producto.Name}</font></h1>
</div>

<div class="container">
<div class="card">
<div class="container-fliud">
<div class="wrapper row">
<div class="preview col-md-6">

<img class="img-responsive"
src="/servlet/servlet.FileDownload?file={!producto.ImgId__c}" alt="{!producto.Name}"
width="480" height="430"/>

</div>
<div class="details col-md-6">
<h4 class="product-title"><strong>{!
Producto.Name}</strong></h4>
<div class="rating">
<span class="review-
no"><strong>Categoría: </strong>{!Producto.Categoria__c}</span>
</div>
<br/>
<p class="product-brand"><strong>Marca:
</strong>{!Producto.Marca__c}</p>
<p align="justify" class="product-
description"><strong>Descripción: </strong>{!Producto.Description}</p>
<h3 class="price">Precio: <span>${!
pbe.UnitPrice}</span></h3>

<!--class sample<div class="action">-->

<div class="section" style="padding-


bottom:20px;">

69
<apex:pageBlock >
<apex:inputHidden id="success" />

<apex:actionFunction name="agregar" action="{!


agregar}" reRender="success" />
<apex:actionFunction name="checar" action="{!checar}"
reRender="success" />

<!--ya servian casi bien(los dibujitos estan adentro del


boton pero no son clickeables
<div id="search">
<font color="white"><i id="search-icon"
class="glyphicon glyphicon-shopping-cart"></i></font>
<input type="button" class="btn btn-primary
btn-lg" name="submit" id="search-input" value="Agregar al carrito"
onclick="agregar();"/>

<font color="white"><i id="search-icon"


class="glyphicon glyphicon-check"></i></font>
<input type="button" class="btn btn-success
btn-lg" name="submit" id="search-input" value="Checkout" onclick="agregar();"/>
</div>
-->

<!--estos son los que nunca sirvieron bien (hay


que dar varios clicks)
<apex:actionFunction name="doSomething"
action="{!landing}" reRender="success" oncomplete="redirect();"/>
<apex:actionFunction name="redirect" action="{!
redirect}" />
<button class="btn btn-primary btn-lg"
onclick="agregar();"><span class="glyphicon glyphicon-shopping-cart" aria-
hidden="true"></span> Agregar al carrito</button>

<button class="btn btn-success btn-lg"


onclick="doSomething(); "><span class="glyphicon glyphicon-check" aria-
hidden="true"></span> Checkout</button>
-->

<!--usando apexcommandbutton (1 solo y un


grupo de 2) sirven bien pero sin imagen
<apex:commandButton action="{!agregar}"
value='Agregar al carrito' styleClass="btn btn-primary btn-lg" />

70
<apex:outputPanel styleClass="btn-group"
layout="block">
<apex:commandButton action="{!
agregar}" value='Agregar al carrito' styleClass="btn btn-primary btn-lg" />
<apex:commandButton action="{!
agregar}" value='Checkout' styleClass="btn btn-success btn-lg" />
</apex:outputPanel>
-->

<br/>
<h6>
<a onclick="agregar();" class= "btn btn-primary btn-lg"><span
class="glyphicon glyphicon-shopping-cart" style="cursor:pointer;"></span> Agregar al
carrito</a>
<a onclick="checar();" class= "btn btn-success btn-lg"><span
class="glyphicon glyphicon-check" style="cursor:pointer;"></span> Checkout</a>
</h6>
</apex:pageBlock>
</div>
</div>
</div>
</div>
</div>
</div>

<hr class="featurette-divider"/>

<!-- FOOTER -->


<footer>
<p class="pull-right"><a href="#">Regresar al inicio</a></p>
<p>&copy; 2017, CompuSoluciones, SA de CV. Todos los derechos
reservados.
&middot; <a href="/Contacto?cart={!cart}">Contáctanos</a> &middot; </p>
</footer>

</div><!-- /.container -->

<!-- Bootstrap core JavaScript


================================================== -->
<!-- Placed at the end of the document so the pages load faster -->

71
<script
src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
<!--Linea original-->
<!--<script>window.jQuery || document.write('<script
src="../../assets/js/vendor/jquery.min.js"><\/script>')</script>-->
<!--Linea modificada marca error sintaxis-->
<!--<script>window.jQuery || document.write('<script src="{!
URLFOR($Resource.bootstrap, \'bootstrap-
3.3.7/docs/assets/js/vendor/jquery.min.js\')}"><\/script>')</script>-->
<!--Nose si esta sirviendo?-->
<script>if(!window.jQuery) {
var script = document.createElement("script");
script.src ="{!URLFOR($Resource.bootstrap, 'bootstrap-
3.3.7/docs/assets/js/vendor/jquery.min.js')}";
document.body.appendChild(script);
}</script>
<script src="{!URLFOR($Resource.bootstrap, 'bootstrap-
3.3.7/dist/js/bootstrap.min.js')}"></script>
<!-- Just to make our placeholder images work. Don't actually copy the next
line! -->
<script src="{!URLFOR($Resource.bootstrap, 'bootstrap-
3.3.7/docs/assets/js/vendor/holder.min.js')}"></script>
<!-- IE10 viewport hack for Surface/desktop Windows 8 bug -->
<script src="{!URLFOR($Resource.bootstrap, 'bootstrap-
3.3.7/docs/assets/js/ie10-viewport-bug-workaround.js')}"></script>
</body>

</html>

</apex:form>
</apex:page>

- Contacto
<apex:page showHeader="false" sidebar="false" standardStylesheets="false"
standardController="Product2" extensions="CartController">
<apex:form >
<html lang="en">
<head>
<meta charset="utf-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=edge"/>
<meta name="viewport" content="width=device-width, initial-scale=1"/>
<!-- The above 3 meta tags *must* come first in the head; any other head content
must come *after* these tags -->
<meta name="description" content=""/>
<meta name="author" content=""/>

72
<link rel="icon" href="{!URLFOR($Resource.bootstrap, 'bootstrap-
3.3.7/docs/favicon.ico')}"/>

<title>CompuSoluciones: Contacto</title>

<!-- Bootstrap core CSS -->


<link href="{!URLFOR($Resource.bootstrap, 'bootstrap-
3.3.7/dist/css/bootstrap.min.css')}" rel="stylesheet"/>

<!-- IE10 viewport hack for Surface/desktop Windows 8 bug -->


<link href="{!URLFOR($Resource.bootstrap, 'bootstrap-3.3.7/assets/css/ie10-
viewport-bug-workaround.css')}" rel="stylesheet"/>

<!-- Just for debugging purposes. Don't actually copy these 2 lines! -->
<!--[if lt IE 9]><script src="../../assets/js/ie8-responsive-file-warning.js"></script><!
[endif]-->
<script src="{!URLFOR($Resource.bootstrap, 'bootstrap-3.3.7/assets/js/ie-emulation-
modes-warning.js')}"></script>

<!-- HTML5 shim and Respond.js for IE8 support of HTML5 elements and media
queries -->
<!--[if lt IE 9]>
<script src="https://oss.maxcdn.com/html5shiv/3.7.3/html5shiv.min.js"></script>
<script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script>
<![endif]-->

<!-- Custom styles for this template -->


<link href="{!URLFOR($Resource.carrusel)}" rel="stylesheet"/>

</head>

<!-- NAVBAR
================================================== -->
<body>
<div class="navbar-wrapper">
<div class="container">
<nav class="navbar navbar-inverse navbar-static-top">
<div class="container">
<div class="navbar-header" style="background:
url(https://c.na59.visual.force.com/resource/1502465258000/logocompu); background-
size: 400px 100px; background-position: center top; background-repeat: no-repeat">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse"
data-target="#navbar" aria-expanded="false" aria-controls="navbar">
<span class="sr-only">Toggle navigation</span>

73
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<!-- <img src="{!URLFOR($Resource.logocompu)}" width="350" height="90"
align="center" alt="logo" />-->
<a class="navbar-brand" href="#"> CompuSoluciones</a>
</div>
<div id="navbar" class="navbar-collapse collapse">
<ul class="nav navbar-nav">
<li class="active"><a href="/home?cart={!cart}">Inicio</a></li>
<li><a href="/Contacto?cart={!cart}">Contacto</a></li>
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button"
aria-haspopup="true" aria-expanded="false">Categorías <span
class="caret"></span></a>
<ul class="dropdown-menu">
<li><a href="/home?cat=Almacenamiento&cart={!
cart}">Almacenamiento</a></li>
<li><a href="/home?cat=Computadoras&cart={!
cart}">Computadoras</a></li>
<li><a href="/home?cat=Gabinetes&cart={!cart}">Gabinetes</a></li>
<li><a href="/home?cat=Kits Teclado y Mouse&cart={!cart}">Kits Teclado y
Mouse</a></li>
<li><a href="/home?cat=Memorias RAM&cart={!cart}">Memorias
RAM</a></li>
<li><a href="/home?cat=Procesadores&cart={!
cart}">Procesadores</a></li>
<li><a href="/home?cat=Software&cart={!cart}">Software</a></li>
<li><a href="/home?cat=Tarjetas Madre&cart={!cart}">Tarjetas
Madre</a></li>
<li role="separator" class="divider"></li>
<li class="dropdown-header">Paquetes</li>
<li><a href="/home?cat=Computadoras&paq=si&cart={!
cart}">Computadoras</a></li>
</ul>
</li>
</ul>
<ul class="nav navbar-nav navbar-right">
<!--no enfocarse mejor hacer integracion con salesforce-->

</ul>
</div>
</div>
</nav>
</div>

74
</div>

<div class="container marketing">

<div class="page-header">
<br/><br/>
<h1>Contacto</h1>
</div>
<address>
<strong>CompuSoluciones</strong> <br/>
San Fernando 514, Tlalpan Centro <br/><br/>
<strong>Email: </strong><a href="mailto:#">
contacto@compusoluciones.com </a><br/><br/>
<strong>Phone: </strong>(55) 69646688
</address>

<div class="container">
<div class="row">
<div class="col-md-6 col-md-offset-3">
<div class="well well-sm">
<form class="form-horizontal" action="" method="post">
<apex:inputHidden id="success" />
<apex:actionFunction name="dejarMensaje" action="{!dejarMensaje}"
reRender="success" />
<fieldset>
<legend class="text-center">Déjanos un mensaje</legend>

<!-- Name input-->


<div class="form-group">
<label class="col-md-3 control-label" for="name">Nombre</label>
<div class="col-md-9">
<apex:inputText value="{!nombre}" html-placeholder="Tu nombre"
styleClass="form-control" required="true"/>
</div>
</div>

<!-- Email input-->


<div class="form-group">
<label class="col-md-3 control-label" for="email">Correo</label>

75
<div class="col-md-9">
<apex:inputField value="{!contacto.email}" styleClass="form-control" html-
placeholder="Debes ingresar un correo válido" required="true"/>
</div>
</div>

<!-- Subject input-->


<div class="form-group">
<label class="col-md-3 control-label" for="email">Asunto</label>
<div class="col-md-9">
<apex:inputText value="{!asunto}" html-placeholder="Asunto del mensaje"
styleClass="form-control" required="true"/>
</div>
</div>

<!-- Message body -->


<div class="form-group">
<label class="col-md-3 control-label" for="message">Mensaje</label>
<div class="col-md-9">
<apex:inputTextarea rows="5" value="{!mensajem}" html-placeholder="Favor
de escribir tu mensaje aquí..." required="true" cols="50" />
</div>
</div>

<!-- Form actions -->


<div class="form-group">
<div class="col-md-12 text-right"><br/>
<!--<button type="submit" class="btn btn-primary btn-lg">Enviar</button>-->
<a href="#" class="btn btn-primary btn-lg" onclick="dejarMensaje();"><span
class="glyphicon glyphicon-envelope"></span> Enviar</a>
</div>
</div>
</fieldset>
</form>
</div>
</div>
</div>
</div>

<hr class="featurette-divider"/>

<!-- FOOTER -->


<footer>

76
<p class="pull-right"><a href="#">Regresar al inicio</a></p>
<p>&copy; 2017, CompuSoluciones, SA de CV. Todos los derechos reservados.
&middot; <a href="/Contacto?cart={!cart}">Contáctanos</a> &middot; </p>
</footer>

</div><!-- /.container -->

<!-- Bootstrap core JavaScript


================================================== -->
<!-- Placed at the end of the document so the pages load faster -->
<script
src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
<!--Linea original-->
<!--<script>window.jQuery || document.write('<script
src="../../assets/js/vendor/jquery.min.js"><\/script>')</script>-->
<!--Linea modificada marca error sintaxis-->
<!--<script>window.jQuery || document.write('<script src="{!
URLFOR($Resource.bootstrap, \'bootstrap-
3.3.7/docs/assets/js/vendor/jquery.min.js\')}"><\/script>')</script>-->
<!--Nose si esta sirviendo?-->
<script>if(!window.jQuery) {
var script = document.createElement("script");
script.src ="{!URLFOR($Resource.bootstrap, 'bootstrap-
3.3.7/docs/assets/js/vendor/jquery.min.js')}";
document.body.appendChild(script);
}</script>
<script src="{!URLFOR($Resource.bootstrap, 'bootstrap-
3.3.7/dist/js/bootstrap.min.js')}"></script>
<!-- Just to make our placeholder images work. Don't actually copy the next line! -->
<script src="{!URLFOR($Resource.bootstrap, 'bootstrap-
3.3.7/docs/assets/js/vendor/holder.min.js')}"></script>
<!-- IE10 viewport hack for Surface/desktop Windows 8 bug -->
<script src="{!URLFOR($Resource.bootstrap, 'bootstrap-3.3.7/docs/assets/js/ie10-
viewport-bug-workaround.js')}"></script>
</body>

</html>
</apex:form>
</apex:page>

-compra
<apex:page showHeader="false" sidebar="false" standardStylesheets="false"
standardController="Opportunity" extensions="CheckoutController">
<!--cambie a cartcontroller porque productcontroller pide un id y marca error..-->

77
<apex:form id="contenido">
<html lang="en">
<head>
<meta charset="utf-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=edge"/>
<meta name="viewport" content="width=device-width, initial-scale=1"/>
<!-- The above 3 meta tags *must* come first in the head; any other head
content must come *after* these tags -->
<meta name="description" content=""/>
<meta name="author" content=""/>
<link rel="icon" href="{!URLFOR($Resource.bootstrap, 'bootstrap-
3.3.7/docs/favicon.ico')}"/>

<title>Detalle de su compra </title>

<!-- Bootstrap core CSS -->


<link href="{!URLFOR($Resource.bootstrap, 'bootstrap-
3.3.7/dist/css/bootstrap.min.css')}" rel="stylesheet"/>

<!-- IE10 viewport hack for Surface/desktop Windows 8 bug -->


<link href="{!URLFOR($Resource.bootstrap, 'bootstrap-3.3.7/assets/css/ie10-
viewport-bug-workaround.css')}" rel="stylesheet"/>

<!-- Just for debugging purposes. Don't actually copy these 2 lines! -->
<!--[if lt IE 9]><script src="../../assets/js/ie8-responsive-file-
warning.js"></script><![endif]-->
<script src="{!URLFOR($Resource.bootstrap, 'bootstrap-3.3.7/assets/js/ie-
emulation-modes-warning.js')}"></script>

<!-- HTML5 shim and Respond.js for IE8 support of HTML5 elements and
media queries -->
<!--[if lt IE 9]>
<script
src="https://oss.maxcdn.com/html5shiv/3.7.3/html5shiv.min.js"></script>
<script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script>
<![endif]-->

<!-- Custom styles for this template -->


<link href="{!URLFOR($Resource.carrusel)}" rel="stylesheet"/>

</head>

<!-- NAVBAR
================================================== -->

78
<body>
<div class="navbar-wrapper">
<div class="container">
<nav class="navbar navbar-inverse navbar-static-top">
<div class="container">
<div class="navbar-header" style="background:
url(https://c.na59.visual.force.com/resource/1502465258000/logocompu); background-
size: 400px 100px; background-position: center top; background-repeat: no-repeat">
<button type="button" class="navbar-toggle collapsed" data-
toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<!-- <img src="{!URLFOR($Resource.logocompu)}" width="350"
height="90" align="center" alt="logo" />-->
<a class="navbar-brand" href="/home"> CompuSoluciones</a>
</div>
<div id="navbar" class="navbar-collapse collapse">
<ul class="nav navbar-nav">
<li><a href="/Contacto">Contacto</a></li>

</ul>
</div>
</div>
</nav>
</div>
</div>

<div class="container marketing">

<div class="page-header">
<div class="jumbotron">
<div class="alert alert-success" role="alert">
<strong>¡Enhorabuena!</strong> Tu compra fue realizada exitosamente.
</div><br/>
<h3><strong>Hola {!venta.Account.Name}, </strong><br/></h3>

<p>Gracias por tu pedido. CompuSoluciones agradece tu compra. Los


detalles de tu pedido se indican a continuación.</p>

79
<p>Estado de tu compra: {!venta.Estado_compra__c} </p>
<p>ID del pedido: {!venta.Id} </p>
<p>Realizado el día
<apex:outputText value="{0, date, MMMM d',' yyyy}">
<apex:param value="{!venta.CloseDate}" />
</apex:outputText></p>
</div>
</div>

<h3><strong>Detalles del pedido: </strong> </h3> <br/>


<table id="cart" class="table table-hover table-condensed">
<thead>
<tr>
<th style="width:50%">Producto</th>
<th style="width:10%">Precio</th>
<th style="width:8%">Cantidad</th>
<th style="width:22%" class="text-
center">Subtotal</th>
<th style="width:10%"></th>
</tr>
</thead>
<tbody>
<apex:repeat value="{!productos}"
var="producto" >
<tr>
<td data-th="Product">
<div class="row">
<div class="col-sm-2
hidden-xs"><img src="/servlet/servlet.FileDownload?file={!producto.product2.ImgId__c}"
alt="{!producto.product2.Name}" class="img-responsive" width="140" height="140"
style="margin: 0 auto;"/></div>
<div class="col-sm-10">
<h4
class="nomargin">{!producto.product2.Name}</h4>
<p>{!
producto.product2.Description}</p>
</div>
</div>
</td>
<td data-th="Price">${!
producto.Unitprice}</td>
<td data-th="Quantity">{!
producto.Quantity}</td>
<td data-th="Subtotal" class="text-
center">${!producto.TotalPrice}</td>
<td class="actions" data-th="">

80
</td>
</tr>
</apex:repeat>
</tbody>

</table>

<h3 align="right"><strong>Importe total ${!venta.Amount}</strong></h3>

<hr class="featurette-divider"/>
<h3><strong>Datos de la tarjeta usada: </strong> </h3> <br/>
<p>Tipo de la tarjeta: {!venta.Tipo_de_tarjeta__c} </p>
<p>Nombre del propietario: {!venta.Nombre_en_tarjeta__c}</p>
<p>Número de la tarjeta: {!venta.Numero_de_tarjeta__c} </p>
<p>Código de la tarjeta: {!venta.Codigo_de_la_tarjeta__c} </p>
<p>Fecha de expiración: {!venta.Fecha_de_expiracion__c} </p>

<hr class="featurette-divider"/>

<!-- FOOTER -->


<footer>
<p class="pull-right"><a href="#">Regresar al inicio</a></p>
<p>&copy; 2017, CompuSoluciones, SA de CV. Todos los derechos
reservados.
&middot; <a href="/Contacto">Contáctanos</a> &middot; </p>
</footer>

</div><!-- /.container -->

<!-- Bootstrap core JavaScript


================================================== -->
<!-- Placed at the end of the document so the pages load faster -->
<script
src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
<!--Linea original-->
<!--<script>window.jQuery || document.write('<script
src="../../assets/js/vendor/jquery.min.js"><\/script>')</script>-->
<!--Linea modificada marca error sintaxis-->
<!--<script>window.jQuery || document.write('<script src="{!
URLFOR($Resource.bootstrap, \'bootstrap-
3.3.7/docs/assets/js/vendor/jquery.min.js\')}"><\/script>')</script>-->
<!--Nose si esta sirviendo?-->

81
<script>if(!window.jQuery) {
var script = document.createElement("script");
script.src ="{!URLFOR($Resource.bootstrap, 'bootstrap-
3.3.7/docs/assets/js/vendor/jquery.min.js')}";
document.body.appendChild(script);
}</script>
<script src="{!URLFOR($Resource.bootstrap, 'bootstrap-
3.3.7/dist/js/bootstrap.min.js')}"></script>
<!-- Just to make our placeholder images work. Don't actually copy the next
line! -->
<script src="{!URLFOR($Resource.bootstrap, 'bootstrap-
3.3.7/docs/assets/js/vendor/holder.min.js')}"></script>
<!-- IE10 viewport hack for Surface/desktop Windows 8 bug -->
<script src="{!URLFOR($Resource.bootstrap, 'bootstrap-
3.3.7/docs/assets/js/ie10-viewport-bug-workaround.js')}"></script>
</body>

</html>

</apex:form>
</apex:page>

- Compusoluciones
<apex:page sidebar="false" showHeader="false" standardController="Account"
extensions="CartController" standardStylesheets="false">

<html lang="en">
<head>
<meta charset="utf-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=edge"/>
<meta name="viewport" content="width=device-width, initial-scale=1"/>
<!-- The above 3 meta tags *must* come first in the head; any other head content
must come *after* these tags -->
<meta name="description" content=""/>
<meta name="author" content=""/>
<link rel="icon" href="{!URLFOR($Resource.bootstrap, 'bootstrap-
3.3.7/docs/favicon.ico')}"/>

<title>Justified Nav Template for Bootstrap</title>

<!-- Bootstrap core CSS -->


<link href="{!URLFOR($Resource.bootstrap, 'bootstrap-
3.3.7/dist/css/bootstrap.min.css')}" rel="stylesheet"/>

<!-- IE10 viewport hack for Surface/desktop Windows 8 bug -->

82
<link href="{!URLFOR($Resource.bootstrap, 'bootstrap-3.3.7/assets/css/ie10-
viewport-bug-workaround.css')}" rel="stylesheet"/>

<!-- Custom styles for this template -->


<link href="{!URLFOR($Resource.bootstrap, 'bootstrap-3.3.7/docs/examples/justified-
nav/justified-nav.css')}" rel="stylesheet" />

<!-- Just for debugging purposes. Don't actually copy these 2 lines! -->
<!--[if lt IE 9]><script src="../../assets/js/ie8-responsive-file-warning.js"></script><!
[endif]-->
<script src="{!URLFOR($Resource.bootstrap, 'bootstrap-3.3.7/assets/js/ie-emulation-
modes-warning.js')}"></script>

<!-- HTML5 shim and Respond.js for IE8 support of HTML5 elements and media
queries -->
<!--[if lt IE 9]>
<script src="https://oss.maxcdn.com/html5shiv/3.7.3/html5shiv.min.js"></script>
<script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script>
<![endif]-->
</head>

<body>

<div class="container">

<!-- The justified navigation menu is meant for single line per list item.
Multiple lines will require custom code not provided by Bootstrap. -->
<div class="masthead">
<h3 class="text-muted">CompuSoluciones</h3>
<nav>
<ul class="nav nav-justified">
<li class="active"><a href="#">Home</a></li>
<li><a href="#">Projects</a></li>
<li><a href="#">Services</a></li>
<li><a href="#">Downloads</a></li>
<li><a href="#">About</a></li>
<li><a href="#">Contact</a></li>
</ul>
</nav>
</div>

<!-- Jumbotron -->


<div class="jumbotron">
<h1>Marketing stuff!</h1>

83
<p class="lead">Cras justo odio, dapibus ac facilisis in, egestas eget quam. Fusce
dapibus, tellus ac cursus commodo, tortor mauris condimentum nibh, ut fermentum
massa justo sit amet.</p>
<p><a class="btn btn-lg btn-success" href="/home" role="button" >Get started
today</a></p>
<apex:form >
<apex:pageBlock >
<apex:commandButton action="{!landing}" value="Convertir" />
</apex:pageBlock>
</apex:form>
</div>

<!-- Example row of columns -->


<div class="row">
<div class="col-lg-4">
<h2>Safari bug warning!</h2>
<p class="text-danger">As of v9.1.2, Safari exhibits a bug in which resizing your
browser horizontally causes rendering errors in the justified nav that are cleared upon
refreshing.</p>
<p>Donec id elit non mi porta gravida at eget metus. Fusce dapibus, tellus ac
cursus commodo, tortor mauris condimentum nibh, ut fermentum massa justo sit amet
risus. Etiam porta sem malesuada magna mollis euismod. Donec sed odio dui. </p>
<p><a class="btn btn-primary" href="#" role="button">View details
&raquo;</a></p>
</div>
<div class="col-lg-4">
<h2>Heading</h2>
<p>Donec id elit non mi porta gravida at eget metus. Fusce dapibus, tellus ac
cursus commodo, tortor mauris condimentum nibh, ut fermentum massa justo sit amet
risus. Etiam porta sem malesuada magna mollis euismod. Donec sed odio dui. </p>
<p><a class="btn btn-primary" href="#" role="button">View details
&raquo;</a></p>
</div>
<div class="col-lg-4">
<h2>Heading</h2>
<p>Donec sed odio dui. Cras justo odio, dapibus ac facilisis in, egestas eget
quam. Vestibulum id ligula porta felis euismod semper. Fusce dapibus, tellus ac cursus
commodo, tortor mauris condimentum nibh, ut fermentum massa.</p>
<p><a class="btn btn-primary" href="#" role="button">View details
&raquo;</a></p>
</div>
</div>

<!-- Site footer -->


<footer class="footer">
<p>&copy; 2017 CompuSoluciones, SA de CV.</p>

84
</footer>

</div> <!-- /container -->

<!-- IE10 viewport hack for Surface/desktop Windows 8 bug -->


<script src="../../assets/js/ie10-viewport-bug-workaround.js"></script>
</body>
</html>

</apex:page>

6.Implementación

Ventana principal - Inicio

85
Barra de navegación – Inicio – Contacto – Categorías – Búsqueda - Carrito

Ventana de contacto

86
Categorías

87
Buscar

Articulo – detalles

88
Carrito

Realizar pago

89
Información pago

Correo pago

90
Detalle de la compra _URL del correo

Gestión de productos

91
92
93
7.Conclusiones

Una vez que la aplicación ya ha sido desarrollada y está funcionando en un


entorno estable, llega el momento de sacar ciertas conclusiones sobre el
proceso que se ha seguido en el proceso hasta llegar a este punto y si se han
conseguido los puntos que inicialmente se querían cubrir.

En cuanto a la consecución de los objetivos iniciales, se ha conseguido el crear


un sitio web ligero, intuitivo para los usuarios que tienen que acceder a él para
realizar sus compras, y aportando una labor comercial además de la práctica
de compras. La aplicación cuenta con las opciones básicas para la tramitación
de pedidos y consulta de los productos de la empresa, así como un área de
administración básica de los datos que componen la plataforma.

8. Referencias bibliográficas

1.‐ https://resources.docs.salesforce.com/200/latest/es‐mx/sfdc/pdf/extend_click.pdf
2.‐ https://resources.docs.salesforce.com/198/latest/es‐es/sfdc/pdf/basics.pdf
3.‐ https://www.inboundcycle.com/bid/196021/El‐carrito‐de‐compra‐en‐el‐e‐commerce
4.‐ https://www.entrepreneur.com/article/269396
5.‐ https://help.salesforce.com/articleView?id=code_about.htm&type=5
6.‐ https://www.salesforce.com/mx/crm/
7.‐ https://www.oracle.com/mx/applications/erp/what‐is‐erp.html
8.‐ http://www.staffcreativa.pe/blog/carritos‐compra‐online/
9.‐ http://doitcloudconsulting.mx/blog/nube.html#post
10.‐ http://doitcloudconsulting.mx/blog/transformacion_digital.html
11.‐ https://www.salesforce.com/mx/cloud‐computing/
12.‐ https://appexchange.salesforce.com/listingDetail?listingId=a0N3A00000EJbxNUAT
13.‐ https://hipertextual.com/archivo/2013/05/entendiendo‐html5‐guia‐para‐principiantes/
14.‐ http://es.html.net/tutorials/css/lesson1.php
15.‐ Klaus Schwab (autor del libro “la cuarta revolución industrial" y director ejecutivo del Foro
Económico Mundial

94

You might also like