* Add basic files structure for spanish translation of the doc * Translate the video tutorial index page * Translate Before Start page * Translate What is an app page * Translate the Bench page * Translate Conslusion page of the tutorial * Translate to spanish Tutorial Index page * Translate to spanish Reports page * Translate to Spanish Roles Page * Translate to Spanish the Tutorial Model Page * Translate to Spanish the tutorial Single Doctypes page * Translate to Spanish the tutorial Doctype files structure page * Translate to Spanish the tutorial Start Bench page * Translate to Spanish the tutorial New App page * Translate to Spanish the tutorial Client Side Script page * Translate to Spanish the tutorial Users and records page * Translate to Spanish the tutorial Setting Up the site page * Translate to Spanish the tutorial Task Runner page * Translate to Spanish the tutorial Controllers Page * Translate to Spanish the tutorial Doctypes page * Translate to Spanish the tutorial Naming And Linking page * Translate to Spanish the tutorial Web Views pageversion-14
@@ -0,0 +1,3 @@ | |||
# Desarrollo de aplicaciones con Frappe | |||
{index} |
@@ -0,0 +1,4 @@ | |||
tutorial | |||
bench | |||
guides | |||
videos |
@@ -0,0 +1,10 @@ | |||
# Qué es una aplicación | |||
Una aplicación en Frappe es una aplicación estandar en Python. Puedes estructurar una aplicación hecha en Frappe de la misma forma que estructuras una aplicación en Python. | |||
Para implementación, Frappe usa los Python Setuptools, lo que nos permite facilmente instalar la aplicación en cualquier computadora. | |||
El Framework Frappe provee una interfaz WSGI y para el desarrollo puedes usar el servidor interno de frappe llamado Werkzeug. Para implementación en producción, recomendamos usar nginx y gunicorn. | |||
Frappe tambien soporta la architectura multi-tenant. Esto significa que puedes correr varios "sitios" en su instalación, cada uno de ellos estará poniendo a disposición un conjunto de aplicaciones y usuarios. La base de datos para cada sitio es separada. | |||
{next} |
@@ -0,0 +1,71 @@ | |||
# Antes de empezar | |||
<p class="lead">Una lista de recursos que te ayudaran a inicar con el desarrollo de aplicaciones usando Frappe.</p> | |||
--- | |||
#### 1. Python | |||
Frappe usa Python (v2.7) como lenguaje de parte del servidor. Es altamente recomendable aprender Python antes de iniciar a crear aplicaciones con Frappe. | |||
Para escribir código de calidad del lado del servidor, también debes incluir pruebas automatizadas. | |||
Recursos: | |||
1. [Tutorial sobre Python de Codecademy](https://www.codecademy.com/learn/python) | |||
1. [Tutorial Oficial de Python](https://docs.python.org/2.7/tutorial/index.html) | |||
1. [Tutorial básico de Test-driven development](http://code.tutsplus.com/tutorials/beginning-test-driven-development-in-python--net-30137) | |||
--- | |||
#### 2. MariaDB / MySQL | |||
Para crear aplicaciones con frappe, debes entender los conceptops básicos del manejo de base de datos, como instalarlas, acceder, crear nueva base de datos, y hacer consultas básicas con SQL. | |||
Recursos: | |||
1. [Tutorial sobre SQL de Codecademy](https://www.codecademy.com/learn/learn-sql) | |||
1. [Tutorial Básico de MySQL de DigitalOcean](https://www.digitalocean.com/community/tutorials/a-basic-mysql-tutorial) | |||
1. [Introducción a MariaDB](https://mariadb.com/kb/en/mariadb/documentation/getting-started/) | |||
--- | |||
#### 3. HTML / CSS | |||
Si quieres construir interfaces de usuario usando Frappe, necesitas aprender los conceptops básicos de HTML / CSS y el framework de CSS Bootstrap. | |||
Recursos: | |||
1. [Tutorial sobre HTML/CSS de Codecademy](https://www.codecademy.com/learn/learn-html-css) | |||
1. [Introducción a Bootstrap](https://getbootstrap.com/getting-started/) | |||
--- | |||
#### 4. JavaScript and jQuery | |||
Para modificar formularios y crear interfaces de usuarios interactivas, deberías aprender JavaScript y la librería JQuery. | |||
Recursos: | |||
1. [Tutorial sobre JavaScript de Codecademy](https://www.codecademy.com/learn/learn-javascript) | |||
1. [Tutorial sobre jQuery de Codecademy](https://www.codecademy.com/learn/jquery) | |||
--- | |||
#### 5. Manejar de plantillas Jinja | |||
Si estas modificando plantillas de Impresión o Páginas Web, tienes que aprender a utilizar el manejar de plantillas Jinja. Es una forma facíl de crear páginas web dinámicas. | |||
Recursos: | |||
1. [Primer on Jinja Templating](https://realpython.com/blog/python/primer-on-jinja-templating/) | |||
1. [Documentación oficial](http://jinja.pocoo.org/) | |||
--- | |||
#### 6. Git and GitHub | |||
Aprende como contribuir en un proyecto de código abierto usando Git y GitHub, dos increíbles herramientes que te ayudan a gestionar tu código y compartirlo con otros. | |||
Recursos: | |||
1. [Tutorial Básico de Git](https://try.github.io) | |||
2. [Cómo contribuir al Código Abierto](https://opensource.guide/how-to-contribute/) | |||
--- | |||
Cuando estes listo, puedes intentar [crear una aplicación simple]({{ docs_base_url }}/user/es/tutorial/app) usando Frappe. |
@@ -0,0 +1,11 @@ | |||
# Instalando el Frappe Bench | |||
La forma más facíl de configurar frappe en un computador usando sitemas basados en Unix es usando frappe-bench. Lee las instrucciones detalladas acerca de como instalarlo usando Frappe Bench. | |||
> [https://github.com/frappe/bench](https://github.com/frappe/bench) | |||
Con Frappe Bench vas a poder configurar y hostear multiples aplicaciones y sitios, también va a configurar un entorno virtual de Python por lo que vas a tener un entorno apartado para correr sus aplicaciones (y no va a tener conflictos de versiones con otros entornos de desarrollo). | |||
El comando `bench` va a ser instalado en su sistema para ayudarlo en la fase de desarrollo y el manejo de la aplicación. | |||
{next} |
@@ -0,0 +1,5 @@ | |||
# Conclusión | |||
Esperamos que esto te haya dado una idea de como son desarrolladas las aplicaicones en Frappe. El objetivo era de que de manera breve se tocaran varios de los aspectos del desarrollo de aplicaciones. Para obtener ayuda en inconvenientes o temas específicos, favor revisar el API. | |||
Para ayuda, únete a la comunidad en el [canal de chat en Gitter](https://gitter.im/frappe/erpnext) o el [foro de desarrollo](https://discuss.erpnext.com) |
@@ -0,0 +1,59 @@ | |||
# Controladores (Controllers) | |||
El siguiente paso va a ser agregar métodos y eventos a los modelos. En la aplicación, debemos asegurar que si una Library Transaction es creada, el Article que se solicita debe estar en disponibilidad y el miembro que lo solicita debe tener una membresía (membership) válida. | |||
Para esto, podemos escribir una validación que se verifique justo en el momento que una Library Transaction es guardada. Para lograrlo, abre el archivo `library_management/doctype/library_transaction/library_transaction.py`. | |||
Este archivo es el controlador para el objeto Library Transaction. En este archivo puedes escribir métodos para: | |||
1. `before_insert` | |||
1. `validate` (Antes de insertar o actualizar) | |||
1. `on_update` (Despues de guardar) | |||
1. `on_submit` (Cuando el documento es presentado como sometido o presentado) | |||
1. `on_cancel` | |||
1. `on_trash` (antes de ser eliminado) | |||
Puedes escribir métodos para estos eventos y estos van a ser llamados por el framework automóticamente cuando el documento pase por uno de esos estados. | |||
Aquí les dejo el controlador completo: | |||
from __future__ import unicode_literals | |||
import frappe | |||
from frappe import _ | |||
from frappe.model.document import Document | |||
class LibraryTransaction(Document): | |||
def validate(self): | |||
last_transaction = frappe.get_list("Library Transaction", | |||
fields=["transaction_type", "transaction_date"], | |||
filters = { | |||
"article": self.article, | |||
"transaction_date": ("<=", self.transaction_date), | |||
"name": ("!=", self.name) | |||
}) | |||
if self.transaction_type=="Issue": | |||
msg = _("Article {0} {1} no ha sido marcado como retornado desde {2}") | |||
if last_transaction and last_transaction[0].transaction_type=="Issue": | |||
frappe.throw(msg.format(self.article, self.article_name, | |||
last_transaction[0].transaction_date)) | |||
else: | |||
if not last_transaction or last_transaction[0].transaction_type!="Issue": | |||
frappe.throw(_("No puedes retornar un Article que no ha sido prestado.")) | |||
En este script: | |||
1. Obtenemos la última transacción antes de la fecha de la transacción actual usando la funcion `frappe.get_list` | |||
1. Si la última transacción es algo que no nos gusta, lanzamos una excepción usando `frappe.throw` | |||
1. Usamos el método `_("texto")` para identificar las cadenas que pueden ser traducidas. | |||
Verifica si sus validaciones funcionan creando nuevos registros. | |||
<img class="screenshot" alt="Transaction" src="{{docs_base_url}}/assets/img/lib_trans.png"> | |||
#### Depurando | |||
Para depurar, siempre mantener abierta su consola JS. Verifíca rastros de Javascript y del Servidor. | |||
Siempre verifica su terminal para las excepciones. Cualquier **500 Internal Server Errors** va a ser mostrado en la terminal en la que está corriendo el servidor. | |||
{next} |
@@ -0,0 +1,31 @@ | |||
# Estructura de directorios de un DocType | |||
Despues de guardar los DocTypes, revisa que los archivos `.json` y `.py` fuueron creados en módulo `apps/library_management/library_management`. La estructura de directorios despues de crear los modelos debería ser similar a la siguiente: | |||
. | |||
├── MANIFEST.in | |||
├── README.md | |||
├── library_management | |||
.. | |||
│ ├── library_management | |||
│ │ ├── __init__.py | |||
│ │ └── doctype | |||
│ │ ├── __init__.py | |||
│ │ ├── article | |||
│ │ │ ├── __init__.py | |||
│ │ │ ├── article.json | |||
│ │ │ └── article.py | |||
│ │ ├── library_member | |||
│ │ │ ├── __init__.py | |||
│ │ │ ├── library_member.json | |||
│ │ │ └── library_member.py | |||
│ │ ├── library_membership | |||
│ │ │ ├── __init__.py | |||
│ │ │ ├── library_membership.json | |||
│ │ │ └── library_membership.py | |||
│ │ └── library_transaction | |||
│ │ ├── __init__.py | |||
│ │ ├── library_transaction.json | |||
│ │ └── library_transaction.py | |||
{next} |
@@ -0,0 +1,96 @@ | |||
# DocType | |||
Despues de crear los Roles, vamos a crear los **DocTypes** | |||
Para crear un nuevo **DocType**, ir a: | |||
> Developer > Documents > Doctype > New | |||
<img class="screenshot" alt="New Doctype" src="{{docs_base_url}}/assets/img/doctype_new.png"> | |||
En el DocType, primero el módulo, lo que en nuestro caso es **Library Management** | |||
#### Agregando Campos | |||
En la tabla de campos, puedes agregar los campos (propiedades) de el DocType (Article). | |||
Los campos son mucho más que solo columnas en la base de datos, pueden ser: | |||
Fields are much more than database columns, they can be: | |||
1. Columnas en la base de datos | |||
1. Ayudantes de diseño (definidores de secciones / columnas) | |||
1. Tablas hijas (Tipo de dato Table) | |||
1. HTML | |||
1. Acciones (botones) | |||
1. Adjuntos o Imagenes | |||
Vamos a agregar los campos de el Article. | |||
<img class="screenshot" alt="Adding Fields" src="{{docs_base_url}}/assets/img/doctype_adding_field.png"> | |||
Cuando agredas los campos, necesitas llenar el campo **Type**. **Label** es opcional para los Section Break y Column Break. **Name** (`fieldname`) es el nombre de la columna en la tabla de la base de datos y tambien el nombre de la propiedad para el controlador. Esto tiene que ser *code friendly*, i.e. Necesitas poner _ en lugar de " ". Si dejas en blanco este campo, se va a llenar automáticamente al momento de guardar. | |||
Puedes establecer otras propiedades al campo como si es obligatorio o no, si es de solo lectura, etc. | |||
Podemos agregar los siguientes campos: | |||
1. Article Name (Data) | |||
2. Author (Data) | |||
3. Description | |||
4. ISBN | |||
5. Status (Select): Para los campos de tipo Select, vas a escribir las opciones. Escribe **Issued** y **Available** cada una en una linea diferente en la caja de texto de Options. Ver el diagrama más abajo. | |||
6. Publisher (Data) | |||
7. Language (Data) | |||
8. Image (Adjuntar Imagen) | |||
#### Agregar permisos | |||
Despues de agregar los campos, dar click en hecho y agrega una nueva fila en la sección de Permission Roles. Por ahora, vamos a darle accesos Lectura, Escritura, Creación y Reportes al Role **Librarian**. Frappe cuenta con un sistema basados en el modelo de Roles finamente granulado. Puedes cambiar los permisos más adealante usando el **Role Permissions Manager** desde **Setup**. | |||
<img class="screenshot" alt="Adding Permissions" src="{{docs_base_url}}/assets/img/doctype_adding_permission.png"> | |||
#### Guardando | |||
Dar click en el botón de **Guardar**. Cuando el botón es clickeado, una ventana emergente le va a preguntar por el nombre. Vamos a darle el nombre de **Article** y guarda el DocType. | |||
Ahora accede a mysql y verifica que en la base de datos que se ha creado una nueva tabla llamada tabArticle. | |||
$ bench mysql | |||
Welcome to the MariaDB monitor. Commands end with ; or \g. | |||
Your MariaDB connection id is 3931 | |||
Server version: 5.5.36-MariaDB-log Homebrew | |||
Copyright (c) 2000, 2014, Oracle, Monty Program Ab and others. | |||
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement. | |||
MariaDB [library]> DESC tabArticle; | |||
+--------------+--------------+------+-----+---------+-------+ | |||
| Field | Type | Null | Key | Default | Extra | | |||
+--------------+--------------+------+-----+---------+-------+ | |||
| name | varchar(255) | NO | PRI | NULL | | | |||
| creation | datetime(6) | YES | | NULL | | | |||
| modified | datetime(6) | YES | | NULL | | | |||
| modified_by | varchar(40) | YES | | NULL | | | |||
| owner | varchar(60) | YES | | NULL | | | |||
| docstatus | int(1) | YES | | 0 | | | |||
| parent | varchar(255) | YES | MUL | NULL | | | |||
| parentfield | varchar(255) | YES | | NULL | | | |||
| parenttype | varchar(255) | YES | | NULL | | | |||
| idx | int(8) | YES | | NULL | | | |||
| article_name | varchar(255) | YES | | NULL | | | |||
| status | varchar(255) | YES | | NULL | | | |||
| description | text | YES | | NULL | | | |||
| image | varchar(255) | YES | | NULL | | | |||
| publisher | varchar(255) | YES | | NULL | | | |||
| isbn | varchar(255) | YES | | NULL | | | |||
| language | varchar(255) | YES | | NULL | | | |||
| author | varchar(255) | YES | | NULL | | | |||
+--------------+--------------+------+-----+---------+-------+ | |||
18 rows in set (0.00 sec) | |||
Como puedes ver, junto con los DocFields, algunas columnas fueron agregadas a la tabla. Las importantes a notar son, la clave primaria, `name`, `owner`(El usuario que creo el registro), | |||
`creation` y `modified` (timestamps para la creación y última modificación). | |||
{next} |
@@ -0,0 +1,39 @@ | |||
## Añadir Scripts a nuestros formularios | |||
Ya que tenemos creado el sistema básico que funciona sin problemas sin escribir una linea de código. Vamos a escribir algunos scripts | |||
para hablar la aplicación más interactiva y agregar validaciones para que el usuario no pueda introducir información erronea. | |||
### Scripts del lado del Cliente | |||
En el DocType **Library Transaction**, solo tenemos campo para el Nombre del miembro. No hemos creado dos campos. Esto podría ser dos campos (y probablemente debería), pero para los motivos del ejemplo, vamos a considerar que tenemos que implementarlo así. Para hacerlo vamos a tener que escribir un manejador de eventos para el evento que ocurre cuando el usuario selecciona el campo `library_member` y luego accede a la información del miembro desde el servidor usando el REST API y cambia los valores en el formulario. | |||
Para empezar el script, en el directorio `library_management/doctype/library_transaction`, crea un nuevo archivo `library_transaction.js`. | |||
Este archivo va a ser ejecutado automáticamente cuando la primer Library Transaction es abierta por el usuario. En este archivo, podemos establecer eventos y escribir otras funciones. | |||
#### library_transaction.js | |||
frappe.ui.form.on("Library Transaction", "library_member", | |||
function(frm) { | |||
frappe.call({ | |||
"method": "frappe.client.get", | |||
args: { | |||
doctype: "Library Member", | |||
name: frm.doc.library_member | |||
}, | |||
callback: function (data) { | |||
frappe.model.set_value(frm.doctype, | |||
frm.docname, "member_name", | |||
data.message.first_name | |||
+ (data.message.last_name ? | |||
(" " + data.message.last_name) : "")) | |||
} | |||
}) | |||
}); | |||
1. **frappe.ui.form.on(*doctype*, *fieldname*, *handler*)** es usada para establecer un manejador de eventos cuando la propiedad library_member es seleccionada. | |||
1. En el manejador, vamos a disparar una llamada AJAX a `frappe.client.get`. En respuesta obtenemos el objeto consultado en formato JSON. [Aprende más acerca del API](/frappe/user/en/guides/integration/rest_api). | |||
1. Usando **frappe.model.set_value(*doctype*, *name*, *fieldname*, *value*)** cambiamos el valor en el formulario. | |||
**Nota:** Para verificar si su script funciona, recuerda Recargar/Reload la página antes de probar el script. Los cambios realizados a los script del lado del Cliente no son automáticamente cargados nuevamente cuando estas en modo desarrollador. | |||
{next} |
@@ -0,0 +1,34 @@ | |||
# Tutorial sobre Frappe | |||
En esta guía, vamos a mostrarte como crear una aplicación desde cero usando **Frappe**. Usando el ejemplo de un Sistema de Gestión de Librería. Vamos a cubrir: | |||
1. Instalación | |||
1. Creando una nueva App | |||
1. Creando Modelos | |||
1. Creando Usuarios y Registros | |||
1. Creando Controladores | |||
1. Creando Vistas Web | |||
1. Configurando Hooks y Tareas | |||
## Para Quién es este tutorial? | |||
Esta guía esta orientada para desarrolladores de software que estan familiarizados con el proceso de como son creadas y servidas las aplicaciones web. El Framework Frappe está escrito en Python y usa MariaDB como base de datos y para la creación de las vistas web usa HTML/CSS/Javascript. Por lo que sería excelente si estas familiarizado con estas tecnologías. | |||
Por lo menos, si nunca haz usado Python antes, deberías tomar un tutorial rápido antes de iniciar con este tutorial. | |||
Frappe usa el sistema de gestión de versiones en GitHub. También, es importante estar familiarizado con los conceptos básicos de git y tener una cuenta en GitHub para manejar sus aplicaciones. | |||
## Ejemplo | |||
Para esta guía, vamos a crear una aplicación simple llamada **Library Management**. En esta aplicación vamos a tener los siguientes modelos (Permanecerán en inglés para que coincidan con las imagenes): | |||
1. Article (Libro o cualquier otro artículo que pueda ser prestado) | |||
1. Library Member | |||
1. Library Transaction (Entrega o Retorno de un artículo) | |||
1. Library Membership (Un período en el que un miembro esta permitido hacer una trasacción) | |||
1. Library Management Setting (Configuraciones generales, como el tiempo que dura el prestamo de un artículo) | |||
La interfaz de usuario (UI) para la aplicación va a ser el **Frappe Desk**, un entorno para UI basado en el navegador y viene integrado en Frappe donde los formularios son generados automáticamente desde los modelos y los roles y permisos son aplicados. | |||
También, vamos a crear vistas webs para la librería donde los usuarios pueden buscar los artículos desde una página web. | |||
{index} |
@@ -0,0 +1,19 @@ | |||
before | |||
app | |||
bench | |||
new-app | |||
setting-up-the-site | |||
start | |||
models | |||
roles | |||
doctypes | |||
naming-and-linking | |||
doctype-directory-structure | |||
users-and-records | |||
form-client-scripting | |||
controllers | |||
reports | |||
web-views | |||
single-doctypes | |||
task-runner | |||
conclusion |
@@ -0,0 +1,19 @@ | |||
# Creando Modelos | |||
El siguiente paso es crear los modelos que discutimos en la introducción. En Frappe, los modelos son llamados **DocTypes**. Puedes crear nuevos DocTypes desde el UI Escritorio de Frappe. **DocTypes** son creados de campos llamados **DocField** y los permisos basados en roles son integrados dentro de los modelos, estos son llamados **DocPerms**. | |||
Cuando un DocType es guardado, se crea una nueva tabla en la base de datos. Esta tabla se nombra `tab[doctype]`. | |||
Cuando creas un **DocType** una nueva carpeta es creada en el **Module** y un archivo JSON y una platilla de un controlador en Python son creados automáticamente. Cuando modificas un DocType, el archivo JSON es modificado y cada vez que se ejecuta `bench migrate`, sincroniza el archivo JSON con la tabla en la base de datos. Esto hace que sea más facíl reflejar los cambios hechos al esquema y migrarlo. | |||
### Modo desarrollador | |||
Para crear modelos, debes setear `developer_mode` a 1 en el archivo `site_config.json` ubicados en /sites/library y ejecuta el comando `bench clear-cache` o usa el menú de usuario en el Escritorio y da click en "Recargar/Reload" para que los cambios tomen efecto. Deberías poder ver la aplicación llamada "Developer" en su escritorio. | |||
{ | |||
"db_name": "bcad64afbf", | |||
"db_password": "v3qHDeVKvWVi7s97", | |||
"developer_mode": 1 | |||
} | |||
{next} |
@@ -0,0 +1,71 @@ | |||
# Nombrando y Asociando DocType | |||
Vamos a crear otro DocType y guardarlo: | |||
1. Library Member (First Name, Last Name, Email Address, Phone, Address) | |||
<img class="screenshot" alt="Doctype Saved" src="{{docs_base_url}}/assets/img/naming_doctype.png"> | |||
#### Nombrando DocTypes | |||
Los DocTypes pueden ser nombrados en diferentes maneras: | |||
1. Basados en un campo | |||
1. Basados en una serie | |||
1. A traves del controlador (vía código) | |||
1. Con un promt | |||
Esto puede ser seteado a traves del campo **Autoname**. Para el controlador, dejar en blanco. | |||
> **Search Fields**: Un DocType puede ser nombrado por serie pero seguir teniendo la necesidad de ser buscado por nombre. En nuestro caso, el Article va ser buscado por el título o el nombre del autor. Por lo que vamos a poner esos campos en el campo de search. | |||
<img class="screenshot" alt="Autonaming and Search Field" src="{{docs_base_url}}/assets/img/autoname_and_search_field.png"> | |||
#### Campo de Enlace y Campo Select | |||
Las claves foraneas son específicadas en Frappe como campos **Link** (Enlace). El DocType debe ser mencionado en el area de texto de Options. | |||
En nuestro ejemplo, en el DocType de Library Transaction,tenemos que enlazar los dos DocTypes de Library Member and the Article. | |||
**Nota:** Recuerda que los campos de Enlace no son automáticamente establecidos como claves foraneas en la base de datos MariaDB, porque esto crearía un indice en la columna. Las validaciones de claves foraneas son realizadas por el Framework. | |||
<img class="screenshot" alt="Link Field" src="{{docs_base_url}}/assets/img/link_field.png"> | |||
Por campos de tipo Select, como mencionamos antes, agrega varias opciones en la caja de texto **Options**, cada una en una nueva linea. | |||
<img class="screenshot" alt="Select Field" src="{{docs_base_url}}/assets/img/select_field.png"> | |||
De manera similar continua haciendo los otros modelos. | |||
#### Valores enlazados | |||
Un patrón estandar es que cuando seleccionas un ID, dice **Library Member** en **Library Membership**, entonces el nombre y apellido del miembro deberian ser copiados en campos relevantes de el Doctype Library Membership Transaction. | |||
Para hacer esto, podemos usar campos de solo lectura y en opciones, podemos especificar el nombre del link (enlace) y el campo o propiedad que deseas obtener. Para este ejempo en **Member First Name** podemos especificar `library_member.first_name`. | |||
<img class="screenshot" alt="Fetch values" src="{{docs_base_url}}/assets/img/fetch.png"> | |||
### Completar los modelos | |||
En la misma forma, puedes completar todos los modelos, todos los campos deben verse de esta manera | |||
#### Article | |||
<img class="screenshot" alt="Article" src="{{docs_base_url}}/assets/img/doctype_article.png"> | |||
#### Library Member | |||
<img class="screenshot" alt="Library Member" src="{{docs_base_url}}/assets/img/doctype_lib_member.png"> | |||
#### Library Membership | |||
<img class="screenshot" alt="Library Membership" src="{{docs_base_url}}/assets/img/doctype_lib_membership.png"> | |||
#### Library Transaction | |||
<img class="screenshot" alt="Library Transaction" src="{{docs_base_url}}/assets/img/doctype_lib_trans.png"> | |||
> Asegurate de dar permiso a **Librarian** en cada DocType | |||
{next} |
@@ -0,0 +1,54 @@ | |||
# Creando una nueva aplicación | |||
Una vez el bench esté instalado, vas a ver dos directorios principales, `apps` and `sites`. Todas las aplicaciones van a ser instaladas en apps. | |||
Para crear una nueva aplicación, debes posicionarte en el directorio del bench y ejecutar `bench new-app {app_name}` y llenar los detalles de la aplicación. Esto a va crear los directorios y archivos necesarios para una aplicación. | |||
$ bench new-app library_management | |||
App Title (defaut: Lib Mgt): Library Management | |||
App Description: App for managing Articles, Members, Memberships and Transactions for Libraries | |||
App Publisher: Frappe | |||
App Email: info@frappe.io | |||
App Icon (default 'octicon octicon-file-directory'): octicon octicon-book | |||
App Color (default 'grey'): #589494 | |||
App License (default 'MIT'): GNU General Public License | |||
### Estructura de una aplicación | |||
La aplicación va a ser creada en el directorio llamado `library_management` y va a tener la siguiente estructura: | |||
. | |||
├── MANIFEST.in | |||
├── README.md | |||
├── library_management | |||
│ ├── __init__.py | |||
│ ├── config | |||
│ │ ├── __init__.py | |||
│ │ └── desktop.py | |||
│ ├── hooks.py | |||
│ ├── library_management | |||
│ │ └── __init__.py | |||
│ ├── modules.txt | |||
│ ├── patches.txt | |||
│ └── templates | |||
│ ├── __init__.py | |||
│ ├── generators | |||
│ │ └── __init__.py | |||
│ ├── pages | |||
│ │ └── __init__.py | |||
│ └── statics | |||
├── license.txt | |||
├── requirements.txt | |||
└── setup.py | |||
1. `config` contiene la información de configuración de la aplicación. | |||
1. `desktop.py` es donde los íconos del escritorio pueden ser agregados al mismo. | |||
1. `hooks.py` es donde se configuran las integraciones con el entorno y otras aplicaciones. | |||
1. `library_management` (dentro) es un **módulo** que está contenido. En Frappe, un **módulo** es donde los modelos y controladores se almacenan. | |||
1. `modules.txt` contiene la lista de **módulos** en la aplicación. Cuando creas un nuevo módulo, es obligatorio que lo agregues a este archivo. | |||
1. `patches.txt` es donde los patches para migraciones son establecidos. Son módulos de Python referenciados usando la nomenclatura de punto. | |||
1. `templates` es el directorio donde son mantenidos las plantillas de vistas web. Plantillas para **Login** y otras páginas estandar estan contenidas en Frappe. | |||
1. `generators` son donde las plantillas para los modelos son almacenadas, donde cada instancia de modelo tiene una ruta web separada, por ejemplo un **Blog Post** donde cada post tiene una url única. En Frappe, el manejador de plantillas utilizado es Jinja2. | |||
1. `pages` es donde las rutas simples son almacenadas. Por ejemplo para un tipo de página "/blog". | |||
{next} |
@@ -0,0 +1,7 @@ | |||
# Reportes | |||
Puedes dar click en el texto que dice Reportes en el panel lateral izquierdo para ver los registros de manera tabulada. | |||
<img class="screenshot" alt="Report" src="{{docs_base_url}}/assets/img/report.png"> | |||
{next} |
@@ -0,0 +1,14 @@ | |||
# Creando Roles | |||
Antes de crear los Modelos, debemos crear los Roles que van a establecer los permisos en el Modelo. En nuestro ejemplo vamos a tener dos Roles: | |||
1. Librarian | |||
1. Library Member | |||
Para crear un nuevo Role, ir a: | |||
> Setup > Users > Role > New | |||
<img class="screenshot" alt="Adding Roles" src="{{docs_base_url}}/assets/img/roles_creation.png"> | |||
{next} |
@@ -0,0 +1,68 @@ | |||
# Configurando el Site | |||
Vamos a crear un nuevo Site llamado `library`. | |||
*Nota: Antes de crear cualquier Site, necesitas hacer unos cambios en su instalación de MariaDB.* | |||
*Copia la siguiente configuración por defecto de ERPNext en su archivo `my.cnf`.* | |||
[mysqld] | |||
innodb-file-format=barracuda | |||
innodb-file-per-table=1 | |||
innodb-large-prefix=1 | |||
character-set-client-handshake = FALSE | |||
character-set-server = utf8mb4 | |||
collation-server = utf8mb4_unicode_ci | |||
[mysql] | |||
default-character-set = utf8mb4 | |||
Ahora puedes instalar un nuevo site, ejecutando el comando `bench new-site library`. | |||
La ejecución del comando anterior va a generar una nueva base de datos, un directorio en la carpeta sites y va a instalar `frappe` (el cual también es una aplicación!) en el nuevo site. | |||
La aplicación `frappe` tiene dos módulos integrados que son **Core** y **Website**. El módulo Core contiene los modelos básicos para la aplicación. Frappe es un Framework con muchas funcionalidades incluidas y viene con muchos modelos integrados. Estos modelos son llamados **DocTypes**. Vamos a ver más de esto en lo adelante. | |||
$ bench new-site library | |||
MySQL root password: | |||
Installing frappe... | |||
Updating frappe : [========================================] | |||
Updating country info : [========================================] | |||
Set Administrator password: | |||
Re-enter Administrator password: | |||
Installing fixtures... | |||
*** Scheduler is disabled *** | |||
### Estructura de un Site | |||
Un nuevo directorio ha sido creado dentro de la carpeta `sites` llamado `library`. La estructura siguiente es la que trae por defecto un site. | |||
. | |||
├── locks | |||
├── private | |||
│ └── backups | |||
├── public | |||
│ └── files | |||
└── site_config.json | |||
1. `public/files` es donde se almacenan los archivos subidos por los usuarios. | |||
1. `private/backups` es donde se almacenan los backups o copias de respaldo. | |||
1. `site_config.json` es donde todas las configuraciones a nivel de sites son almacenadas. | |||
### Configurando un Site por defecto | |||
En caso que tengas varios sites en tu Bench, debes usar `bench use [nombre_site]` para especificar el site por defecto. | |||
Ejemplo: | |||
$ bench use library | |||
### Instalar Aplicaciones | |||
Ahora vamos a instalar nuestra aplicación `library_management` en nuestro site `library`. | |||
1. Instalar la aplicación library_management en el site library se logra ejecutando el siguiente comando: `bench --site [nombre_site] install-app [nombre_app]` | |||
Ejemplo: | |||
$ bench --site library install-app library_management | |||
{next} |
@@ -0,0 +1,9 @@ | |||
# DocTypes Simples | |||
Una aplicación normalmente va a tener una página de configuración. En nuestra aplicación, podemos definir una página donde específiquemos el período de prestamos. Necesitaremos almacenar esta propiedad. En Frappe, esto puede lograrse usando los DocType de tipo **Simple**. Un DocType Simple es como el patrón Singleton en Java. Es un objeto con tan solo una instancia. Vamos a llamarlo **Library Managment Settings**. | |||
Para crear un Single DocType, marca el checkbox **Is Single**. | |||
<img class="screenshot" alt="Single Doctypes" src="{{docs_base_url}}/assets/img/tab_single.png"> | |||
{next} |
@@ -0,0 +1,31 @@ | |||
# Iniciando el Bench | |||
Ahora podemos acceder y verificar que todo esta funcionando de forma correcta. | |||
Para iniciar el servidor de desarrollo, ejecuta `bench start`. | |||
$ bench start | |||
13:58:51 web.1 | started with pid 22135 | |||
13:58:51 worker.1 | started with pid 22136 | |||
13:58:51 workerbeat.1 | started with pid 22137 | |||
13:58:52 web.1 | * Running on http://0.0.0.0:8000/ | |||
13:58:52 web.1 | * Restarting with reloader | |||
13:58:52 workerbeat.1 | [2014-09-17 13:58:52,343: INFO/MainProcess] beat: Starting... | |||
Ahora abre tu navegador y ve a la dirección `http://localhost:8000`. Deberías ver la páagina de inicio de sesión si todo salió bien.: | |||
<img class="screenshot" alt="Login Screen" src="{{docs_base_url}}/assets/img/login.png"> | |||
Ahora accede con : | |||
Login ID: **Administrator** | |||
Password : **Usa la contraseña que creaste durante la instalación** | |||
Cuando accedas, deberías poder ver la página de inicio (Desk). | |||
<img class="screenshot" alt="Desk" src="{{docs_base_url}}/assets/img/desk.png"> | |||
Como puedes ver, el sistema básico de Frappe viene con algunas aplicaciones preinstaladas como To Do, File Manager etc. Estas aplicaciones pueden integrarse en el flujo de trabajo de su aplicació a medida que avancemos. | |||
{next} |
@@ -0,0 +1,77 @@ | |||
# Tareas Programadas | |||
Finalmente, una aplicación también tiene que mandar notificaciones de email y hacer otros tipos de tareas programadas. En Frappe, si tienes el bench configurado, el programador de tareas es configurado vía Celery usando Redis Queue. | |||
Para agregar un nuevo manejador(Handler) de tareas, ir a `hooks.py` y agrega un nuevo manejador. Los manejadores (Handlers) por defecto son `all`, `daily`, `weekly`, `monthly`. El manejador `all` es llamado cada 3 minutos por defecto. | |||
# Tareas Programadas | |||
# --------------- | |||
scheduler_events = { | |||
"daily": [ | |||
"library_management.tasks.daily" | |||
], | |||
} | |||
Aquí hacemos referencia a una función Python que va a ser ejecutada diariamente. Vamos a ver como se ve esta función: | |||
# Copyright (c) 2013, Frappe | |||
# For license information, please see license.txt | |||
from __future__ import unicode_literals | |||
import frappe | |||
from frappe.utils import datediff, nowdate, format_date, add_days | |||
def daily(): | |||
loan_period = frappe.db.get_value("Library Management Settings", | |||
None, "loan_period") | |||
overdue = get_overdue(loan_period) | |||
for member, items in overdue.iteritems(): | |||
content = """<h2>Following Items are Overdue</h2> | |||
<p>Please return them as soon as possible</p><ol>""" | |||
for i in items: | |||
content += "<li>{0} ({1}) due on {2}</li>".format(i.article_name, | |||
i.article, | |||
format_date(add_days(i.transaction_date, loan_period))) | |||
content += "</ol>" | |||
recipient = frappe.db.get_value("Library Member", member, "email_id") | |||
frappe.sendmail(recipients=[recipient], | |||
sender="test@example.com", | |||
subject="Library Articles Overdue", content=content, bulk=True) | |||
def get_overdue(loan_period): | |||
# check for overdue articles | |||
today = nowdate() | |||
overdue_by_member = {} | |||
articles_transacted = [] | |||
for d in frappe.db.sql("""select name, article, article_name, | |||
library_member, member_name | |||
from `tabLibrary Transaction` | |||
order by transaction_date desc, modified desc""", as_dict=1): | |||
if d.article in articles_transacted: | |||
continue | |||
if d.transaction_type=="Issue" and \ | |||
datediff(today, d.transaction_date) > loan_period: | |||
overdue_by_member.setdefault(d.library_member, []) | |||
overdue_by_member[d.library_member].append(d) | |||
articles_transacted.append(d.article) | |||
Podemos pegar el código anterior en cualquier módulo de Python que sea accesible. La ruta es definida en `hooks.py`, por lo que para nuestro propósito vamos a poner el código en el archivo `library_management/tasks.py`. | |||
Nota: | |||
1. Obtenemos el período de prestamo desde **Library Management Settings** usando la función `frappe.db.get_value`. | |||
1. Ejecutamos una consulta en la base de datos usando la función `frappe.db.sql` | |||
1. Los Email son enviados usando `frappe.sendmail` | |||
{next} |
@@ -0,0 +1,55 @@ | |||
# Creando Usuarios y Registros | |||
Teniendo los modelos creados, podemos empezar a crear registros usando la interfaz gráfica de usuario de Frappe. No necesitas crear vistas! Las vistas en Frappe son automáticamente creadas basadas en las propiedades del DocType. | |||
### 4.1 Creando Usuarios | |||
Para crear registros, primero vamos a crear un Usuario. Para crear un usuario, ir a: | |||
> Setup > Users > User > New | |||
Crea un nuevo Usuario y llena los campos de nombre, primer nombre y nueva contraseña. | |||
Luego dale los Roles de Librarian y de Library Member a este usuario. | |||
<img class="screenshot" alt="Add User Roles" src="{{docs_base_url}}/assets/img/add_user_roles.png"> | |||
Ahora cierra sesión y accede usando las credenciales del nuevo usuario. | |||
### 4.2 Creando Registros | |||
Debes ver un ícono del módulo de Library Management. Dar click en el ícono para entrar a la página del módulo: | |||
<img class="screenshot" alt="Library Management Module" src="{{docs_base_url}}/assets/img/lib_management_module.png"> | |||
Aquí puedes ver los DocTypes que fueron creados para la aplicación. Vamos a comenzar a crear nuevos registros. | |||
Primero vamos a crear un nuevo Article: | |||
<img class="screenshot" alt="New Article" src="{{docs_base_url}}/assets/img/new_article_blank.png"> | |||
Aquí vas a ver que los DocTypes que haz creado han sido renderizados como un formulario. Las validaciones y las otras restricciones también están aplicadas según se diseñaron. Vamos a llenar los datos de un Article. | |||
<img class="screenshot" alt="New Article" src="{{docs_base_url}}/assets/img/new_article.png"> | |||
Puedes agregar una imagen si deseas. | |||
<img class="screenshot" alt="Attach Image" src="{{docs_base_url}}/assets/img/attach_image.gif"> | |||
Ahora vamos a crear un nuevo miembro: | |||
<img class="screenshot" alt="New Library Member" src="{{docs_base_url}}/assets/img/new_member.png"> | |||
Despues de esto, crearemos una nueva membresía (membership) para el miembro. | |||
Si recuerdas, aquí hemos específicado los valores del nombre y apellido del miembro directamente desde el registro del miembro tan pronto selecciones el miembro id, los nombres serán actualizados. | |||
<img class="screenshot" alt="New Library Membership" src="{{docs_base_url}}/assets/img/new_lib_membership.png"> | |||
Como puedes ver la fecha tiene un formato de año-mes-día lo cual es una fecha del sistema. Para seleccionar o cambiar la fecha, tiempo y formatos de números, ir a: | |||
> Setup > Settings > System Settings | |||
<img class="screenshot" alt="System Settings" src="{{docs_base_url}}/assets/img/system_settings.png"> | |||
{next} |
@@ -0,0 +1,64 @@ | |||
# Vistas Web (Web Views) | |||
Frappe tiene dos entornos principales, El escritorio y la Web. El escritorio es una interfaz de usuario controlada con una excelente aplicación AJAX y la web es mas plantillas de HTML tradicionales dispuestas para consumo público. Vistas Web pueden también ser generadas para crear vistas controladas para los usuarios que puedes acceder al sistema pero aún así no tener acceso al escritorio. | |||
En Frappe, Las vistas web son manejadas por plantillas que estan usualmente en el directorio `templates`. Hay dos tipos principales de plantillas. | |||
1. Pages: Estos son plantillas Jinja donde una vista existe solo para una ruta. ejemplo. `/blog`. | |||
2. Generators: Estas son plantiallas donde cada instancia de un DocType tiene una ruta diferente `/blog/a-blog`, `blog/b-blog` etc. | |||
3. Lists and Views: Estos son listas y vistan estandares con la ruta `[doctype]/[name]` y son renderizadas basándose en los permisos. | |||
### Vista Web Estandar | |||
> Esta funcionalidad sigue bajo desarrollo. | |||
Vamos a ver las Vistas web estandar: | |||
Si estas logueado como el usuario de prueba, ve a `/article` y deberías ver la lista de artículos. | |||
<img class="screenshot" alt="web list" src="{{docs_base_url}}/assets/img/web-list.png"> | |||
Da click en uno de los artículos y vas a ver una vista web por defecto | |||
<img class="screenshot" alt="web view" src="{{docs_base_url}}/assets/img/web-view.png"> | |||
Si deseas hacer una mejor vista para la lista de artículos, crea un archivo llamado `row_template.html` en el directorio `library_management/templates/includes/list/`. | |||
Aquí hay un archivo de ejemplo: | |||
{% raw %}<div class="row"> | |||
<div class="col-sm-4"> | |||
<a href="/Article/{{ doc.name }}"> | |||
<img src="{{ doc.image }}" | |||
class="img-responsive" style="max-height: 200px"> | |||
</a> | |||
</div> | |||
<div class="col-sm-4"> | |||
<a href="/Article/{{ doc.name }}"><h4>{{ doc.article_name }}</h4></a> | |||
<p>{{ doc.author }}</p> | |||
<p>{{ (doc.description[:200] + "...") | |||
if doc.description|len > 200 else doc.description }}</p> | |||
<p class="text-muted">Publisher: {{ doc.publisher }}</p> | |||
</div> | |||
</div>{% endraw %} | |||
Aquí, vas a tener todas las propiedades de un artículo en el objeto `doc`. | |||
La lista actualizada debe lucir de esta manera! | |||
<img class="screenshot" alt="new web list" src="{{docs_base_url}}/assets/img/web-list-new.png"> | |||
#### Página de Inicio | |||
Frappe también tiene vistas para el registro de usuarios que incluye opciones de registro usando Google, Facebook y GitHub. Cuando un usuario se registra vía la web, no tiene acceso a la interfaz del Escritorio por defecto. | |||
> Para permitirles a los usuarios acceso al Escritorio, debes especificar que el usuario es de tipo "System User" en Setup > User | |||
Para usuario que no son de tipo System User, podemos especificar una página de inicio por defecto a traves de `hooks.py` basándonos en Role. | |||
Cuando miembros acceden al sistema, deben ser redireccionados a la página `article`, para configurar esto modifica el archivo `library_management/hooks.py` y agrega lo siguiente: | |||
role_home_page = { | |||
"Library Member": "article" | |||
} | |||
{next} |
@@ -0,0 +1,9 @@ | |||
# Videos Tutoriales acerca del Framework Frappe | |||
Este video tutorial de 10 videos va a enseñarte como crear aplicaciones complejas en Frappe. | |||
Prerrequisitos: <a href="{{ docs_base_url }}/user/es/tutorial/before.html" target="_blank">Debes tener conocimientos básicos de Python, Javascript y MySQl antes de empezar este tutorial.</a> | |||
--- | |||
<iframe width="670" height="376" src="https://www.youtube.com/embed/videoseries?list=PL3lFfCEoMxvzHtsZHFJ4T3n5yMM3nGJ1W" frameborder="0" allowfullscreen></iframe> |
@@ -5,3 +5,4 @@ Select your language | |||
1. [English]({{docs_base_url}}/user/en) | |||
1. [Français]({{docs_base_url}}/user/fr) | |||
1. [Português]({{docs_base_url}}/user/pt) | |||
1. [Español]({{docs_base_url}}/user/es) |
@@ -1,3 +1,4 @@ | |||
en | |||
fr | |||
pt | |||
es |