Form login
This commit is contained in:
parent
847b5a560c
commit
59179a17b9
|
@ -6,6 +6,15 @@ __pycache__/
|
|||
# Django stuff:
|
||||
*.log
|
||||
local_settings.py
|
||||
conf.py
|
||||
source/fixtures
|
||||
source/media
|
||||
|
||||
# Sphinx documentation
|
||||
docs/_build/
|
||||
docs/
|
||||
*.ods
|
||||
*.xlsx
|
||||
|
||||
credenciales.conf
|
||||
*.sqlite
|
||||
*.sql
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
falcon
|
||||
Beaker
|
||||
Mako
|
||||
peewee
|
||||
logbook
|
||||
bcrypt
|
|
@ -0,0 +1,10 @@
|
|||
#!/usr/bin/env python
|
||||
from peewee import SqliteDatabase
|
||||
|
||||
|
||||
DEBUG = True
|
||||
ID_SUPPORT = ''
|
||||
|
||||
DATABASE = None
|
||||
if DEBUG:
|
||||
DATABASE = SqliteDatabase('empresalibre.sqlite')
|
|
@ -0,0 +1,12 @@
|
|||
[uwsgi]
|
||||
socket = 127.0.0.1:3032
|
||||
uid = nginx
|
||||
gid = nginx
|
||||
chdir = /srv/app/empresalibre/app
|
||||
wsgi-file = main.py
|
||||
callable = app
|
||||
master = true
|
||||
processes = 4
|
||||
threads = 4
|
||||
#~ stats = 127.0.0.1:9191
|
||||
logger = file:/srv/log/empresalibre-uwsgi.log
|
|
@ -0,0 +1,123 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
import falcon
|
||||
from beaker.middleware import SessionMiddleware
|
||||
|
||||
import util
|
||||
import middleware as MW
|
||||
from models import StorageEngine, get_cp
|
||||
from settings import DEBUG, WITH_LOGIN
|
||||
|
||||
|
||||
class AppPostalCode(object):
|
||||
|
||||
def on_get(self, req, resp):
|
||||
values = req.params
|
||||
req.context['result'] = get_cp(values['cp'])
|
||||
resp.status = falcon.HTTP_200
|
||||
|
||||
|
||||
class AppLogin(object):
|
||||
template = 'login.html'
|
||||
|
||||
def __init__(self, db):
|
||||
self._db = db
|
||||
|
||||
@falcon.after(MW.get_template)
|
||||
def on_get(self, req, resp):
|
||||
resp.status = falcon.HTTP_200
|
||||
|
||||
def on_post(self, req, resp):
|
||||
session = req.env['beaker.session']
|
||||
values = req.params
|
||||
result = self._db.authenticate(values['user'], values['pass'])
|
||||
resp.body = util.dumps(result)
|
||||
if result['login']:
|
||||
session.save()
|
||||
session['user'] = result['user']
|
||||
resp.status = falcon.HTTP_200
|
||||
|
||||
|
||||
class AppLogout(object):
|
||||
|
||||
def __init__(self, db):
|
||||
self._db = db
|
||||
|
||||
def on_get(self, req, resp):
|
||||
session = req.env['beaker.session']
|
||||
session.delete()
|
||||
resp.status = falcon.HTTP_200
|
||||
raise falcon.HTTPTemporaryRedirect('/')
|
||||
|
||||
|
||||
class AppMain(object):
|
||||
template = 'main.html'
|
||||
|
||||
def __init__(self, db):
|
||||
self._db = db
|
||||
|
||||
@falcon.after(MW.get_template)
|
||||
def on_get(self, req, resp):
|
||||
resp.status = falcon.HTTP_200
|
||||
|
||||
|
||||
class AppPartners(object):
|
||||
|
||||
def __init__(self, db):
|
||||
self._db = db
|
||||
|
||||
def on_get(self, req, resp):
|
||||
values = req.params
|
||||
req.context['result'] = self._db.get_partners(values)
|
||||
resp.status = falcon.HTTP_200
|
||||
|
||||
def on_post(self, req, resp):
|
||||
values = req.params
|
||||
if values['id'] == '0':
|
||||
del values['id']
|
||||
req.context['result'] = self._db.new_partner(values)
|
||||
else:
|
||||
req.context['result'] = self._db.update_partner(values)
|
||||
resp.status = falcon.HTTP_200
|
||||
|
||||
def on_delete(self, req, resp):
|
||||
values = req.params
|
||||
if self._db.delete_partner(values['id']):
|
||||
resp.status = falcon.HTTP_200
|
||||
else:
|
||||
resp.status = falcon.HTTP_204
|
||||
|
||||
|
||||
db = StorageEngine()
|
||||
pc = AppPostalCode()
|
||||
login = AppLogin(db)
|
||||
logout = AppLogout(db)
|
||||
main = AppMain(db)
|
||||
partners = AppPartners(db)
|
||||
|
||||
api = falcon.API(middleware=[MW.AuthMiddleware(), MW.JSONTranslator()])
|
||||
api.req_options.auto_parse_form_urlencoded = True
|
||||
api.add_sink(MW.handle_404, '')
|
||||
if WITH_LOGIN:
|
||||
api.add_route('/', login)
|
||||
api.add_route('/logout', logout)
|
||||
api.add_route('/main', main)
|
||||
api.add_route('/partners', partners)
|
||||
api.add_route('/cp', pc)
|
||||
|
||||
|
||||
if DEBUG:
|
||||
api.add_sink(MW.static, '/static')
|
||||
|
||||
|
||||
# Configure the SessionMiddleware
|
||||
session_opts = {
|
||||
'session.type': 'file',
|
||||
'session.cookie_expires': True,
|
||||
'session.data_dir': '/tmp/cache/data',
|
||||
'session.lock_dir': '/tmp/cache/lock',
|
||||
#~ 'session.httponly': True,
|
||||
#~ 'session.secure': True,
|
||||
}
|
||||
app = SessionMiddleware(api, session_opts)
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
[uwsgi]
|
||||
http = 127.0.0.1:8000
|
||||
wsgi-file = main.py
|
||||
callable = app
|
||||
master = true
|
||||
processes = 4
|
||||
threads = 4
|
||||
py-autoreload = 1
|
|
@ -0,0 +1,50 @@
|
|||
#!/usr/bin/env python
|
||||
|
||||
import falcon
|
||||
import util
|
||||
from settings import PATH_STATIC
|
||||
|
||||
|
||||
def handle_404(req, resp):
|
||||
id_session = req.cookies.get('beaker.session.id', '')
|
||||
if id_session:
|
||||
raise falcon.HTTPTemporaryRedirect('/main')
|
||||
raise falcon.HTTPTemporaryRedirect('/')
|
||||
|
||||
|
||||
def get_template(req, resp, resource):
|
||||
session = req.env['beaker.session']
|
||||
resp.content_type = 'text/html'
|
||||
data = {'username': session.get('user', '')}
|
||||
resp.body = util.get_template(resource.template, data)
|
||||
|
||||
|
||||
def static(req, res):
|
||||
path = PATH_STATIC + req.path
|
||||
if util.is_file(path):
|
||||
res.content_type = util.get_mimetype(path)
|
||||
res.stream, res.stream_len = util.get_stream(path)
|
||||
res.status = falcon.HTTP_200
|
||||
else:
|
||||
res.status = falcon.HTTP_404
|
||||
|
||||
|
||||
class AuthMiddleware(object):
|
||||
|
||||
#~ def process_request(self, req, resp):
|
||||
|
||||
def process_resource(self, req, resp, resource, params):
|
||||
paths = ('/main', '/partners', '/cp')
|
||||
id_session = req.cookies.get('beaker.session.id', '')
|
||||
if req.path in paths and not id_session:
|
||||
raise falcon.HTTPTemporaryRedirect('/')
|
||||
|
||||
|
||||
class JSONTranslator(object):
|
||||
|
||||
def process_response(self, req, resp, resource):
|
||||
if 'result' not in req.context:
|
||||
return
|
||||
resp.body = util.dumps(req.context['result'])
|
||||
|
||||
|
|
@ -0,0 +1,263 @@
|
|||
#!/usr/bin/env python
|
||||
|
||||
import sys
|
||||
import util
|
||||
from peewee import *
|
||||
from conf import DATABASE
|
||||
from settings import log
|
||||
|
||||
|
||||
database = DATABASE
|
||||
class BaseModel(Model):
|
||||
class Meta:
|
||||
database = database
|
||||
|
||||
|
||||
class Users(BaseModel):
|
||||
username = CharField(max_length=50, unique=True)
|
||||
first_name = CharField(max_length=50, default='')
|
||||
last_name = CharField(max_length=50, default='')
|
||||
email = CharField(max_length=200, default='')
|
||||
password = CharField(max_length=100)
|
||||
is_superuser = BooleanField(default=False)
|
||||
is_admin = BooleanField(default=False)
|
||||
is_staff = BooleanField(default=False)
|
||||
is_active = BooleanField(default=True)
|
||||
date_joined = DateTimeField(default=util.now)
|
||||
last_login = DateTimeField(null=True)
|
||||
|
||||
def __str__(self):
|
||||
t = '{} {} ({})'
|
||||
return t.format(self.first_name, self.last_name, self.username)
|
||||
|
||||
class Meta:
|
||||
order_by = ('username',)
|
||||
|
||||
|
||||
class Clients(BaseModel):
|
||||
id = IntegerField(db_column='cliente_id', primary_key=True)
|
||||
cia = CharField(max_length=11, default='', index=True)
|
||||
rfc = CharField(max_length=13, index=True)
|
||||
name = CharField(db_column='nombre', max_length=60)
|
||||
street = CharField(db_column='calle', max_length=60, default='')
|
||||
num_ext = CharField(db_column='noExterior', max_length=10, default='')
|
||||
num_int = CharField(db_column='noInterior', max_length=10, default='')
|
||||
colonia = CharField(max_length=60, default='')
|
||||
localidad = CharField(max_length=60, default='')
|
||||
municipio = CharField(max_length=60, default='')
|
||||
state = CharField(db_column='estado', max_length=40, default='')
|
||||
country = CharField(db_column='pais', max_length=30, default='')
|
||||
postal_code = CharField(db_column='codigoPostal', max_length=6, default='')
|
||||
email = CharField(db_column='correos', max_length=250, default='')
|
||||
contact = CharField(db_column='nombre_contacto', max_length=60, default='')
|
||||
phone = CharField(db_column='telefono', max_length=40, default='')
|
||||
CUS_ErpId = FixedCharField(max_length=20, default='')
|
||||
CUS_SatClas = FixedCharField(max_length=2, default='')
|
||||
CUS_SatClasNombre = FixedCharField(max_length=50, default='')
|
||||
CUS_DefaultCurrency = FixedCharField(max_length=3, default='')
|
||||
CUS_DefaultCurrencyNombre = FixedCharField(max_length=120, default='')
|
||||
CUS_AccHabe = FixedCharField(max_length=20, default='')
|
||||
CUS_AccHabeNombre = FixedCharField(max_length=60, default='')
|
||||
CUS_AccDebe = FixedCharField(max_length=20, default='')
|
||||
CUS_AccDebeNombre = FixedCharField(max_length=60, default='')
|
||||
|
||||
def __str__(self):
|
||||
t = '{} ({})'
|
||||
return t.format(self.name, self.rfc)
|
||||
|
||||
class Meta:
|
||||
db_table = 'clientes'
|
||||
order_by = ('name',)
|
||||
|
||||
|
||||
class StorageEngine(object):
|
||||
|
||||
def __init__(self):
|
||||
database.connect()
|
||||
|
||||
def authenticate(self, username, password):
|
||||
data = {'login': False, 'msg': 'No Autorizado', 'user': ''}
|
||||
try:
|
||||
obj = Users.get(Users.username==username, Users.is_active==True)
|
||||
except Users.DoesNotExist:
|
||||
return data
|
||||
|
||||
if not util.validate_password(obj.password, password):
|
||||
return data
|
||||
|
||||
obj.last_login = util.now()
|
||||
obj.save()
|
||||
data['msg'] = ''
|
||||
data['login'] = True
|
||||
data['user'] = str(obj)
|
||||
return data
|
||||
|
||||
def get_partners(self, values):
|
||||
if values:
|
||||
id = int(values['id'])
|
||||
row = Clients.select().where(Clients.id==id).dicts()[0]
|
||||
return row
|
||||
else:
|
||||
rows = Clients.select(
|
||||
Clients.id, Clients.cia, Clients.rfc, Clients.name).dicts()
|
||||
return {'ok': True, 'rows': tuple(rows)}
|
||||
|
||||
def new_partner(self, values):
|
||||
fields = util.clean(values)
|
||||
fields['rfc'] = fields['rfc'].upper()
|
||||
Clients.create(**fields)
|
||||
#~ Wend custom ID
|
||||
obj = Clients.select().order_by(Clients.id.desc()).get()
|
||||
row = {
|
||||
'id': obj.id,
|
||||
'cia': obj.cia,
|
||||
'rfc': obj.rfc,
|
||||
'name': obj.name,
|
||||
}
|
||||
data = {'ok': True, 'row': row, 'new': True}
|
||||
return data
|
||||
|
||||
def update_partner(self, values):
|
||||
id = int(values['id'])
|
||||
del values['id']
|
||||
fields = util.clean(values)
|
||||
fields['rfc'] = fields['rfc'].upper()
|
||||
q = Clients.update(**values).where(Clients.id==id)
|
||||
q.execute()
|
||||
row = {
|
||||
'id': id,
|
||||
'cia': fields['cia'],
|
||||
'rfc': fields['rfc'],
|
||||
'name': fields['name'],
|
||||
}
|
||||
data = {'ok': True, 'row': row, 'new': False}
|
||||
return data
|
||||
|
||||
def delete_partner(self, id):
|
||||
q = Clients.delete().where(Clients.id==id)
|
||||
return bool(q.execute())
|
||||
|
||||
|
||||
def get_cp(cp):
|
||||
data = {}
|
||||
rows = util.get_cp(cp)
|
||||
if rows:
|
||||
data = {
|
||||
'estado': rows[0][2],
|
||||
'municipio': rows[0][1],
|
||||
}
|
||||
if len(rows) == 1:
|
||||
data['colonia'] = rows[0][0]
|
||||
else:
|
||||
data['colonia'] = [r[0] for r in rows]
|
||||
#~ print ('DATA', data)
|
||||
return data
|
||||
|
||||
|
||||
def _connect():
|
||||
global database
|
||||
log.info('Connect to DB...')
|
||||
database.connect()
|
||||
return
|
||||
|
||||
|
||||
def create_tables():
|
||||
_connect()
|
||||
tables = [Users, Clients]
|
||||
database.create_tables(tables, True)
|
||||
log.info('Create tables OK...')
|
||||
return
|
||||
|
||||
|
||||
def migrate_tables():
|
||||
_connect()
|
||||
log.info('Migrate tables OK...')
|
||||
return
|
||||
|
||||
|
||||
def create_superuser(username):
|
||||
_connect()
|
||||
ok, password = util.get_pass()
|
||||
if not ok:
|
||||
log.error(password)
|
||||
return
|
||||
try:
|
||||
obj = Users.create(username=username, password=password, is_superuser=True)
|
||||
except IntegrityError:
|
||||
msg = 'El usuario ya existe'
|
||||
log.error(msg)
|
||||
return
|
||||
|
||||
log.info('Create super user OK...')
|
||||
return
|
||||
|
||||
|
||||
def change_password(username):
|
||||
_connect()
|
||||
try:
|
||||
obj = Users.get(username=username)
|
||||
except Users.DoesNotExist:
|
||||
msg = 'El usuario no existe'
|
||||
log.error(msg)
|
||||
return
|
||||
|
||||
ok, password = util.get_pass()
|
||||
if not ok:
|
||||
log.error(password)
|
||||
return
|
||||
|
||||
obj.password = password
|
||||
obj.save()
|
||||
|
||||
log.info('Change password OK...')
|
||||
return
|
||||
|
||||
|
||||
def main(opt, username=''):
|
||||
if opt == '-c':
|
||||
create_tables()
|
||||
elif opt == '-m':
|
||||
migrate_tables()
|
||||
elif opt == '-su':
|
||||
create_superuser(username)
|
||||
elif opt == '-cc':
|
||||
change_password(username)
|
||||
return
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
opt = sys.argv
|
||||
if len(opt) == 1:
|
||||
msg = 'Agrega un argumento'
|
||||
log.error(msg)
|
||||
sys.exit(0)
|
||||
ov = ('-h', '-c', '-m', '-su', '-cc')
|
||||
if not opt[1] in ov:
|
||||
msg = 'Opción no válida. Usa -h para ver las opciones'
|
||||
log.error(msg)
|
||||
sys.exit(0)
|
||||
|
||||
if opt[1] == '-h':
|
||||
msg = '-h Muestra esta ayuda.\n\t' \
|
||||
'-c Crea tablas.\n\t' \
|
||||
'-m Migra tablas.\n\t' \
|
||||
'-su USERNAME Crea Super Usuario.\n\t' \
|
||||
'-cc USERNAME Cambiar contraseña.\n\t'
|
||||
log.info(msg)
|
||||
sys.exit(0)
|
||||
|
||||
if opt[1] == '-su' or opt[1] == '-cc' :
|
||||
if len(opt) == 2:
|
||||
msg = 'Falta el argumento: nombre de usuario'
|
||||
log.error(msg)
|
||||
sys.exit(0)
|
||||
|
||||
try:
|
||||
main(opt[1], opt[2])
|
||||
sys.exit(0)
|
||||
except KeyboardInterrupt:
|
||||
msg = 'La contraseña es necesaria'
|
||||
log.error(msg)
|
||||
sys.exit(0)
|
||||
|
||||
main(opt[1])
|
|
@ -0,0 +1,52 @@
|
|||
#!/usr/bin/env python
|
||||
|
||||
import logbook
|
||||
import os
|
||||
import sys
|
||||
from mako.lookup import TemplateLookup
|
||||
from logbook import Logger, StreamHandler, RotatingFileHandler
|
||||
logbook.set_datetime_format("local")
|
||||
|
||||
from conf import DEBUG
|
||||
|
||||
|
||||
BASE_DIR = os.path.abspath(os.path.dirname(__file__))
|
||||
PATH_STATIC = os.path.abspath(os.path.join(BASE_DIR, '..'))
|
||||
PATH_TEMPLATES = os.path.abspath(os.path.join(BASE_DIR, '..', 'templates'))
|
||||
|
||||
EMAIL_SUPPORT = ('soporte@empresalibre.net',)
|
||||
WITH_LOGIN = True
|
||||
|
||||
DB_CP = 'cp.db'
|
||||
PATH_CP = os.path.abspath(os.path.join(BASE_DIR, '..', 'db', DB_CP))
|
||||
|
||||
template_lookup = TemplateLookup(directories=[PATH_TEMPLATES],
|
||||
input_encoding='utf-8',
|
||||
output_encoding='utf-8')
|
||||
|
||||
LOG_PATH = 'empresalibre.log'
|
||||
LOG_NAME = 'API'
|
||||
LOG_LEVEL = 'INFO'
|
||||
|
||||
format_string = '[{record.time:%d-%b-%Y %H:%M:%S}] ' \
|
||||
'{record.level_name}: ' \
|
||||
'{record.channel}: ' \
|
||||
'{record.message}'
|
||||
|
||||
if DEBUG:
|
||||
LOG_LEVEL = 'DEBUG'
|
||||
StreamHandler(
|
||||
sys.stdout,
|
||||
level=LOG_LEVEL,
|
||||
format_string=format_string).push_application()
|
||||
else:
|
||||
LOG_PATH = '/srv/log/empresalibre.log'
|
||||
RotatingFileHandler(
|
||||
LOG_PATH,
|
||||
backup_count=10,
|
||||
max_size=1073741824,
|
||||
level=LOG_LEVEL,
|
||||
format_string=format_string).push_application()
|
||||
|
||||
log = Logger(LOG_NAME)
|
||||
|
|
@ -0,0 +1,99 @@
|
|||
#!/usr/bin/env python
|
||||
|
||||
import datetime
|
||||
import getpass
|
||||
import json
|
||||
import mimetypes
|
||||
import os
|
||||
import sqlite3
|
||||
import uuid
|
||||
|
||||
import bcrypt
|
||||
|
||||
from settings import template_lookup, PATH_CP
|
||||
|
||||
|
||||
def _get_hash(password):
|
||||
return bcrypt.hashpw(password.encode(), bcrypt.gensalt()).decode()
|
||||
|
||||
|
||||
def validate_password(hashed, password):
|
||||
return bcrypt.hashpw(password.encode(), hashed.encode()) == hashed.encode()
|
||||
|
||||
|
||||
def get_pass():
|
||||
password = getpass.getpass('Introduce la contraseña: ')
|
||||
pass2 = getpass.getpass('Confirma la contraseña: ')
|
||||
|
||||
if password != pass2:
|
||||
msg = 'Las contraseñas son diferentes'
|
||||
return False, msg
|
||||
password = password.strip()
|
||||
if not password:
|
||||
msg = 'La contraseña es necesaria'
|
||||
return False, msg
|
||||
|
||||
return True, _get_hash(password)
|
||||
|
||||
|
||||
def now():
|
||||
return datetime.datetime.now()
|
||||
|
||||
|
||||
def get_token():
|
||||
return _get_hash(uuid.uuid4().hex)
|
||||
|
||||
|
||||
def get_mimetype(path):
|
||||
mt = mimetypes.guess_type(path)[0]
|
||||
return mt or 'application/octet-stream'
|
||||
|
||||
|
||||
def is_file(path):
|
||||
return os.path.isfile(path)
|
||||
|
||||
|
||||
def get_stream(path):
|
||||
return get_file(path), get_size(path)
|
||||
|
||||
|
||||
def get_file(path):
|
||||
return open(path, 'rb')
|
||||
|
||||
|
||||
def get_size(path):
|
||||
return os.path.getsize(path)
|
||||
|
||||
|
||||
def get_template(name, data={}):
|
||||
#~ print ('NAME', name, data)
|
||||
template = template_lookup.get_template(name)
|
||||
return template.render(**data)
|
||||
|
||||
|
||||
def dumps(data):
|
||||
return json.dumps(data, default=str)
|
||||
|
||||
|
||||
def clean(values):
|
||||
for k, v in values.items():
|
||||
if isinstance(v, str):
|
||||
values[k] = v.strip()
|
||||
return values
|
||||
|
||||
|
||||
def get_cp(cp):
|
||||
con = sqlite3.connect(PATH_CP)
|
||||
cursor = con.cursor()
|
||||
sql = """
|
||||
SELECT colonia, municipio, estado
|
||||
FROM colonias, municipios, estados
|
||||
WHERE colonias.id_municipio=municipios.id
|
||||
AND municipios.id_estado=estados.id
|
||||
AND cp=?
|
||||
ORDER BY colonia"""
|
||||
cursor.execute(sql, (cp,))
|
||||
data = cursor.fetchall()
|
||||
cursor.close()
|
||||
con.close()
|
||||
return data
|
Binary file not shown.
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,42 @@
|
|||
|
||||
.login_header {
|
||||
text-align: center;
|
||||
font-weight: bold;
|
||||
font-size: 150%;
|
||||
font-family: Arial, Helvetica, sans-serif;
|
||||
}
|
||||
|
||||
.cmd_edit_parter {
|
||||
max-width: 32px,
|
||||
padding-left: 5px;
|
||||
}
|
||||
|
||||
.center {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.right {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.cmd_close_partner div button {
|
||||
background-color: red !important;
|
||||
border-color: red !important;
|
||||
border-bottom: 1px solid red !important;
|
||||
}
|
||||
|
||||
/*
|
||||
.webix_message_area {
|
||||
position: absolute;
|
||||
margin-top: 25%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
width: 40%;
|
||||
}
|
||||
*/
|
||||
|
||||
.webix_success div {
|
||||
background-color: #00a65a !important;
|
||||
font-size: 1vw;
|
||||
color: white;
|
||||
}
|
|
@ -0,0 +1,95 @@
|
|||
|
||||
/* SideBar*/
|
||||
.webix_sidebar{
|
||||
background: #ECEFF1;
|
||||
}
|
||||
.webix_sidebar .webix_tree_item {
|
||||
color: #454545;
|
||||
height: 35px;
|
||||
line-height: 35px;
|
||||
}
|
||||
.webix_sidebar .webix_scroll_cont > .webix_tree_leaves {
|
||||
padding: 0;
|
||||
}
|
||||
.webix_sidebar .webix_tree_leaves .webix_tree_leaves {
|
||||
margin-left: 0px;
|
||||
}
|
||||
.webix_sidebar_selected,
|
||||
.webix_sidebar_expanded .webix_tree_item:hover{
|
||||
background-color: rgba(0,0,0,0.02);
|
||||
}
|
||||
.webix_sidebar .webix_tree_item.webix_selected,
|
||||
.webix_sidebar .webix_tree_item.webix_selected span{
|
||||
background-color: #27ae60;
|
||||
padding-right:0;
|
||||
}
|
||||
.webix_sidebar .webix_tree_branch_1 .webix_tree_item{
|
||||
padding-left:40px;
|
||||
}
|
||||
.webix_sidebar .webix_tree_branch_1>.webix_tree_item{
|
||||
height: 40px;
|
||||
line-height: 40px;
|
||||
padding-left:0;
|
||||
}
|
||||
.webix_sidebar .webix_tree_branch_1{
|
||||
border-bottom:1px solid #e5e5e5;
|
||||
}
|
||||
.webix_sidebar .webix_tree_item.webix_selected span,
|
||||
.webix_sidebar .webix_tree_item span{
|
||||
margin:0;
|
||||
padding:0px;
|
||||
}
|
||||
.webix_sidebar_icon{
|
||||
width: 40px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.webix_sidebar_dir_icon{
|
||||
float: right;
|
||||
line-height: inherit;
|
||||
}
|
||||
|
||||
/*SubMenu (Popup) */
|
||||
.webix_sidebar_popup{
|
||||
border:none !important;
|
||||
box-shadow: 2px 3px 3px #ddd;
|
||||
}
|
||||
.webix_sidebar_popup, .webix_sidebar_popup .webix_list_item{
|
||||
border-radius:0;
|
||||
}
|
||||
.webix_sidebar_popup_right{
|
||||
box-shadow: -1px 3px 3px #ddd;
|
||||
}
|
||||
/*SubMenu: title*/
|
||||
.webix_sidebar_popup_title{
|
||||
background: #ECEFF1;
|
||||
}
|
||||
.webix_sidebar_popup_title.webix_selected{
|
||||
border-left-color: #27ae60;
|
||||
background: #27ae60;
|
||||
}
|
||||
.webix_sidebar_popup_title .webix_template{
|
||||
line-height: 40px;
|
||||
padding: 0 10px;
|
||||
border: 1px solid #E5E5E5;
|
||||
border-left:none;
|
||||
}
|
||||
.webix_sidebar_selected.webix_sidebar_popup_title .webix_template{
|
||||
background: rgba(0,0,0,0.03);
|
||||
border-left: none;
|
||||
}
|
||||
.webix_sidebar_popup_list .webix_list_item{
|
||||
border-left: 1px solid #E5E5E5;
|
||||
border-right: 1px solid #E5E5E5;
|
||||
}
|
||||
/*SubMenu: list*/
|
||||
.webix_sidebar_popup_list .webix_list_item:first-child{
|
||||
border-top: 1px solid #E5E5E5;
|
||||
}
|
||||
.webix_sidebar_popup_list .webix_list_item:hover{
|
||||
background: #f6f9fb;
|
||||
}
|
||||
|
||||
.webix_sidebar_popup_list .webix_list_item.webix_selected:hover{
|
||||
background: #27ae60;
|
||||
}
|
|
@ -0,0 +1,94 @@
|
|||
/* SideBar*/
|
||||
.webix_sidebar{
|
||||
background: #ECEFF1;
|
||||
}
|
||||
.webix_sidebar .webix_tree_item {
|
||||
color: #454545;
|
||||
height: 35px;
|
||||
line-height: 35px;
|
||||
}
|
||||
.webix_sidebar .webix_scroll_cont > .webix_tree_leaves {
|
||||
padding: 0;
|
||||
}
|
||||
.webix_sidebar .webix_tree_leaves .webix_tree_leaves {
|
||||
margin-left: 0px;
|
||||
}
|
||||
.webix_sidebar_selected,
|
||||
.webix_sidebar_expanded .webix_tree_item:hover{
|
||||
background-color: rgba(0,0,0,0.02);
|
||||
}
|
||||
.webix_sidebar .webix_tree_item.webix_selected,
|
||||
.webix_sidebar .webix_tree_item.webix_selected span{
|
||||
background-color: #ffdb8f;
|
||||
padding-right:0;
|
||||
}
|
||||
.webix_sidebar .webix_tree_branch_1 .webix_tree_item{
|
||||
padding-left:40px;
|
||||
}
|
||||
.webix_sidebar .webix_tree_branch_1>.webix_tree_item{
|
||||
height: 40px;
|
||||
line-height: 40px;
|
||||
padding-left:0;
|
||||
}
|
||||
.webix_sidebar .webix_tree_branch_1{
|
||||
border-bottom:1px solid #e5e5e5;
|
||||
}
|
||||
.webix_sidebar .webix_tree_item.webix_selected span,
|
||||
.webix_sidebar .webix_tree_item span{
|
||||
margin:0;
|
||||
padding:0px;
|
||||
}
|
||||
.webix_sidebar_icon{
|
||||
width: 40px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.webix_sidebar_dir_icon{
|
||||
float: right;
|
||||
line-height: inherit;
|
||||
}
|
||||
|
||||
/*SubMenu (Popup) */
|
||||
.webix_sidebar_popup{
|
||||
border:none !important;
|
||||
box-shadow: 2px 3px 3px #ddd;
|
||||
}
|
||||
.webix_sidebar_popup, .webix_sidebar_popup .webix_list_item{
|
||||
border-radius:0;
|
||||
}
|
||||
.webix_sidebar_popup_right{
|
||||
box-shadow: -1px 3px 3px #ddd;
|
||||
}
|
||||
/*SubMenu: title*/
|
||||
.webix_sidebar_popup_title{
|
||||
background: #ECEFF1;
|
||||
}
|
||||
.webix_sidebar_popup_title.webix_selected{
|
||||
border-left-color: #27ae60;
|
||||
background: #27ae60;
|
||||
}
|
||||
.webix_sidebar_popup_title .webix_template{
|
||||
line-height: 40px;
|
||||
padding: 0 10px;
|
||||
border: 1px solid #E5E5E5;
|
||||
border-left:none;
|
||||
}
|
||||
.webix_sidebar_selected.webix_sidebar_popup_title .webix_template{
|
||||
background: rgba(0,0,0,0.03);
|
||||
border-left: none;
|
||||
}
|
||||
.webix_sidebar_popup_list .webix_list_item{
|
||||
border-left: 1px solid #E5E5E5;
|
||||
border-right: 1px solid #E5E5E5;
|
||||
}
|
||||
/*SubMenu: list*/
|
||||
.webix_sidebar_popup_list .webix_list_item:first-child{
|
||||
border-top: 1px solid #E5E5E5;
|
||||
}
|
||||
.webix_sidebar_popup_list .webix_list_item:hover{
|
||||
background: #f6f9fb;
|
||||
}
|
||||
|
||||
.webix_sidebar_popup_list .webix_list_item.webix_selected:hover{
|
||||
background: #27ae60;
|
||||
}
|
|
@ -0,0 +1,108 @@
|
|||
/* SideBar*/
|
||||
.webix_sidebar{
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
.webix_sidebar .webix_tree_item {
|
||||
color: #454545;
|
||||
height: 35px;
|
||||
line-height: 35px;
|
||||
}
|
||||
.webix_sidebar .webix_scroll_cont > .webix_tree_leaves {
|
||||
padding: 0;
|
||||
}
|
||||
.webix_sidebar_selected{
|
||||
background-color: #f2f2f2;
|
||||
}
|
||||
.webix_sidebar_expanded .webix_tree_item:hover{
|
||||
background-color: #F6F6F6;
|
||||
}
|
||||
.webix_sidebar .webix_tree_item.webix_selected{
|
||||
background-color: #F6F6F6;
|
||||
box-shadow: 5px 0 #3498db inset;
|
||||
}
|
||||
|
||||
.webix_sidebar .webix_tree_item.webix_selected span{
|
||||
background-color: transparent;
|
||||
padding-right:0;
|
||||
}
|
||||
.webix_sidebar .webix_tree_branch_1 .webix_tree_item{
|
||||
padding-left:40px;
|
||||
}
|
||||
.webix_sidebar .webix_tree_branch_1>.webix_tree_item{
|
||||
height: 40px;
|
||||
line-height: 40px;
|
||||
padding-left:0;
|
||||
}
|
||||
.webix_sidebar .webix_tree_branch_1{
|
||||
border-bottom:1px solid #f5f5f5;
|
||||
}
|
||||
.webix_sidebar .webix_tree_item.webix_selected span, .webix_sidebar .webix_tree_item span{
|
||||
margin:0;
|
||||
padding:0px;
|
||||
|
||||
}
|
||||
.webix_sidebar_icon{
|
||||
width: 40px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.webix_sidebar .webix_tree_leaves .webix_tree_leaves {
|
||||
margin-left: 0px;
|
||||
}
|
||||
|
||||
.webix_sidebar_dir_icon{
|
||||
float: right;
|
||||
line-height: inherit;
|
||||
}
|
||||
|
||||
/*Popup*/
|
||||
.webix_sidebar_popup{
|
||||
padding:0 !important;
|
||||
border-radius: 0 !important;
|
||||
margin-top: 0 !important;
|
||||
border:none !important;
|
||||
box-shadow: 2px 3px 3px #ddd;
|
||||
}
|
||||
.webix_sidebar_popup_right{
|
||||
box-shadow: -1px 3px 3px #ddd;
|
||||
}
|
||||
|
||||
.webix_sidebar_popup, .webix_sidebar_popup .webix_list_item,
|
||||
.webix_sidebar_popup .webix_win_body, .webix_win_body > .webix_view,
|
||||
.webix_sidebar_popup .webix_win_content{
|
||||
border-radius:0;
|
||||
}
|
||||
|
||||
.webix_sidebar_popup_title.webix_selected .webix_template{
|
||||
background-color: #F6F6F6;
|
||||
}
|
||||
.webix_sidebar_popup_title .webix_template{
|
||||
line-height: 40px;
|
||||
padding: 0 10px;
|
||||
border: 1px solid #f5f5f5;
|
||||
border-bottom-color: #ddd;
|
||||
border-left:none;
|
||||
}
|
||||
.webix_sidebar_selected.webix_sidebar_popup_title .webix_template{
|
||||
background: #f2f2f2;
|
||||
border-left: none;
|
||||
}
|
||||
.webix_sidebar_popup_list .webix_list_item{
|
||||
border-left: 1px solid #f2f2f2;
|
||||
border-right: 1px solid #f5f5f5;
|
||||
}
|
||||
.webix_sidebar_popup_list .webix_list_item:first-child{
|
||||
border-top: 1px solid #f5f5f5;
|
||||
}
|
||||
|
||||
.webix_sidebar_popup_list .webix_list_item:hover{
|
||||
background-color: #F6F6F6;
|
||||
}
|
||||
.webix_sidebar_popup_list .webix_list_item.webix_selected,
|
||||
.webix_sidebar_popup_list .webix_list_item.webix_selected:hover{
|
||||
background-color: #F6F6F6;
|
||||
box-shadow: 5px 0 #3498db inset;
|
||||
}
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1,14 @@
|
|||
## Font Awesome
|
||||
|
||||
Copyright (C) 2012 by Dave Gandy
|
||||
|
||||
Author: Dave Gandy
|
||||
License: SIL (http://scripts.sil.org/OFL)
|
||||
Homepage: http://fortawesome.github.com/Font-Awesome/
|
||||
|
||||
|
||||
|
||||
## PT Sans Free
|
||||
|
||||
Copyright © 2009 ParaType Ltd.
|
||||
License: Free Font License v1.00
|
Binary file not shown.
File diff suppressed because it is too large
Load Diff
After Width: | Height: | Size: 434 KiB |
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
After Width: | Height: | Size: 754 B |
|
@ -0,0 +1,44 @@
|
|||
|
||||
|
||||
function cmd_new_invoice_click(id, e, node){
|
||||
|
||||
$$('form_invoice').adjust();
|
||||
$$("multi_invoices").setValue("invoices_new")
|
||||
|
||||
};
|
||||
|
||||
|
||||
function cmd_edit_invoice_click(id, e, node){
|
||||
|
||||
$$("multi_invoices").setValue("invoices_new")
|
||||
|
||||
};
|
||||
|
||||
|
||||
function cmd_delete_invoice_click(id, e, node){
|
||||
|
||||
webix.message({type:"success", text: "OK Delete"});
|
||||
|
||||
};
|
||||
|
||||
|
||||
function cmd_save_invoice_click(id, e, node){
|
||||
var form = this.getFormView();
|
||||
|
||||
if (!form.validate()) {
|
||||
webix.message({ type:"error", text:"Valores inválidos" });
|
||||
return
|
||||
}
|
||||
|
||||
$$('form_invoice').clear();
|
||||
$$("multi_invoices").setValue("invoices_home")
|
||||
webix.message({type:"success", text: "Factura guardada correctamente"});
|
||||
|
||||
};
|
||||
|
||||
|
||||
function cmd_cancel_invoice_click(id, e, node){
|
||||
|
||||
$$("multi_invoices").setValue("invoices_home")
|
||||
|
||||
};
|
|
@ -0,0 +1,54 @@
|
|||
|
||||
|
||||
var controllers = {
|
||||
init: function(){
|
||||
//~ Main
|
||||
$$("menu_user").attachEvent("onMenuItemClick", menu_user_click);
|
||||
//~ Partner
|
||||
$$("cmd_new_partner").attachEvent("onItemClick", cmd_new_partner_click);
|
||||
$$("cmd_edit_partner").attachEvent("onItemClick", cmd_edit_partner_click);
|
||||
$$("cmd_delete_partner").attachEvent("onItemClick", cmd_delete_partner_click);
|
||||
$$("cmd_save_partner").attachEvent("onItemClick", cmd_save_partner_click);
|
||||
$$("cmd_cancel_partner").attachEvent("onItemClick", cmd_cancel_partner_click);
|
||||
//~ $$('grid_partners').attachEvent('onItemClick', grid_partners_click);
|
||||
$$('postal_code').attachEvent('onKeyPress', postal_code_key_press);
|
||||
$$('postal_code').attachEvent('onTimedKeyPress', postal_code_key_up);
|
||||
$$('colonia').attachEvent('onFocus', colonia_on_focus)
|
||||
//~ Products
|
||||
$$("cmd_new_product").attachEvent("onItemClick", cmd_new_product_click);
|
||||
$$("cmd_edit_product").attachEvent("onItemClick", cmd_edit_product_click);
|
||||
$$("cmd_delete_product").attachEvent("onItemClick", cmd_delete_product_click);
|
||||
$$("cmd_save_product").attachEvent("onItemClick", cmd_save_product_click);
|
||||
$$("cmd_cancel_product").attachEvent("onItemClick", cmd_cancel_product_click);
|
||||
//~ Invoices
|
||||
$$("cmd_new_invoice").attachEvent("onItemClick", cmd_new_invoice_click);
|
||||
$$("cmd_edit_invoice").attachEvent("onItemClick", cmd_edit_invoice_click);
|
||||
$$("cmd_delete_invoice").attachEvent("onItemClick", cmd_delete_invoice_click);
|
||||
$$("cmd_save_invoice").attachEvent("onItemClick", cmd_save_invoice_click);
|
||||
$$("cmd_cancel_invoice").attachEvent("onItemClick", cmd_cancel_invoice_click);
|
||||
|
||||
get_partners()
|
||||
}
|
||||
};
|
||||
|
||||
function get_partners(){
|
||||
webix.ajax().get("/partners", {}, {
|
||||
error: function(text, data, xhr) {
|
||||
webix.message({ type:"error", text: "Error al consultar"});
|
||||
},
|
||||
success: function(text, data, xhr) {
|
||||
var values = data.json();
|
||||
$$("grid_partners").clearAll();
|
||||
if (values.ok){
|
||||
$$("grid_partners").parse(values.rows, 'json');
|
||||
};
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function menu_user_click(id, e, node){
|
||||
if (id == 1){
|
||||
window.location = '/logout';
|
||||
return
|
||||
}
|
||||
}
|
|
@ -0,0 +1,167 @@
|
|||
|
||||
|
||||
function cmd_new_partner_click(id, e, node){
|
||||
$$('form_partner').setValues({id:0, country:'México'});
|
||||
$$('grid_partners').clearSelection();
|
||||
$$("multi_partners").setValue("partners_new");
|
||||
};
|
||||
|
||||
|
||||
function cmd_edit_partner_click(id, e, node){
|
||||
var row = $$('grid_partners').getSelectedItem();
|
||||
if (row == undefined){
|
||||
webix.message({ type:'error', text:'Selecciona un Cliente' });
|
||||
return
|
||||
};
|
||||
|
||||
webix.ajax().get("/partners", {id:row['id']}, {
|
||||
error: function(text, data, xhr) {
|
||||
webix.message({ type:"error", text: "Error al consultar"});
|
||||
},
|
||||
success: function(text, data, xhr){
|
||||
var values = data.json();
|
||||
$$('form_partner').setValues(values);
|
||||
}
|
||||
});
|
||||
|
||||
$$("multi_partners").setValue("partners_new")
|
||||
};
|
||||
|
||||
|
||||
function cmd_delete_partner_click(id, e, node){
|
||||
var row = $$('grid_partners').getSelectedItem();
|
||||
if (row == undefined){
|
||||
webix.message({ type:'error', text:'Selecciona un Cliente' });
|
||||
return
|
||||
};
|
||||
|
||||
var msg = '¿Estás seguro de eliminar al cliente?<BR><BR>'
|
||||
msg += row['name'] + ' (' + row['rfc'] + ')'
|
||||
msg += '<BR><BR>ESTA ACCIÓN NO SE PUEDE DESHACER'
|
||||
webix.confirm({
|
||||
title:'Eliminar Cliente',
|
||||
ok:'Si',
|
||||
cancel:'No',
|
||||
type:'confirm-error',
|
||||
text:msg,
|
||||
callback:function(result){
|
||||
if (result){
|
||||
delete_partner(row['id'])
|
||||
}
|
||||
}
|
||||
})
|
||||
};
|
||||
|
||||
|
||||
function delete_partner(id){
|
||||
webix.ajax().del('/partners', {id:id}, function(text, xml, xhr){
|
||||
var msg = 'Cliente eliminado correctamente'
|
||||
if (xhr.status == 200){
|
||||
$$('grid_partners').remove(id);
|
||||
webix.message({type:'success', text:msg});
|
||||
} else {
|
||||
msg = 'No se pudo eliminar'
|
||||
webix.message({type:'error', text:msg});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
function cmd_save_partner_click(id, e, node){
|
||||
var form = this.getFormView();
|
||||
|
||||
if (!form.validate()) {
|
||||
webix.message({ type:'error', text:'Valores inválidos' });
|
||||
return
|
||||
}
|
||||
|
||||
var values = form.getValues();
|
||||
webix.ajax().post("partners", values, {
|
||||
error:function(text, data, XmlHttpRequest){
|
||||
msg = 'Ocurrio un error, consulta a soporte técnico';
|
||||
webix.message({type:'error', text:msg});
|
||||
},
|
||||
success:function(text, data, XmlHttpRequest){
|
||||
var values = data.json();
|
||||
if (values.ok) {
|
||||
update_grid_partner(values)
|
||||
} else {
|
||||
webix.message({type:'error', text:values.msg});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
};
|
||||
|
||||
|
||||
function update_grid_partner(values){
|
||||
var msg = 'Cliente agregado correctamente'
|
||||
if (values.new){
|
||||
$$('form_partner').clear()
|
||||
$$('grid_partners').add(values.row)
|
||||
}else{
|
||||
msg = 'Cliente actualizado correctamente'
|
||||
$$("grid_partners").updateItem(values.row['id'], values.row)
|
||||
}
|
||||
$$('multi_partners').setValue('partners_home')
|
||||
webix.message({type:'success', text:msg})
|
||||
}
|
||||
|
||||
|
||||
function cmd_cancel_partner_click(id, e, node){
|
||||
|
||||
$$('multi_partners').setValue('partners_home')
|
||||
|
||||
};
|
||||
|
||||
|
||||
function postal_code_key_up(){
|
||||
var value = this.getValue()
|
||||
var msg = ''
|
||||
if( value.length == 5 ){
|
||||
webix.ajax().get('/cp', {cp:value}, {
|
||||
error: function(text, data, xhr) {
|
||||
webix.message({type:'error', text:'Error al consultar el C.P.'})
|
||||
},
|
||||
success: function(text, data, xhr) {
|
||||
var values = data.json();
|
||||
if (values.estado == undefined){
|
||||
msg = 'No se encontró el C.P., asegurate de que sea correcto'
|
||||
webix.message({type:'error', text:msg})
|
||||
} else {
|
||||
$$('form_partner').setValues({
|
||||
state:values.estado,
|
||||
municipio: values.municipio,
|
||||
colonia:''}, true)
|
||||
$$('colonia').define('suggest', [])
|
||||
if (webix.isArray(values.colonia)){
|
||||
$$('colonia').define('suggest', values.colonia)
|
||||
}else{
|
||||
$$('form_partner').setValues({colonia:values.colonia}, true)
|
||||
}
|
||||
$$('colonia').refresh()
|
||||
$$('form_partner').focus('colonia')
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function postal_code_key_press(code, e){
|
||||
var data = [8, 9, 37, 39, 46]
|
||||
if ( data.indexOf(code) >= 0 ){
|
||||
return true;
|
||||
}
|
||||
|
||||
if ( code < 48 || code > 57){
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function colonia_on_focus(){
|
||||
if ($$(this.config.suggest).getList().config.height > 2){
|
||||
$$(this.config.suggest).show(this.getInputNode())
|
||||
}
|
||||
}
|
|
@ -0,0 +1,43 @@
|
|||
|
||||
|
||||
function cmd_new_product_click(id, e, node){
|
||||
|
||||
$$("multi_products").setValue("product_new")
|
||||
|
||||
};
|
||||
|
||||
|
||||
function cmd_edit_product_click(id, e, node){
|
||||
|
||||
$$("multi_products").setValue("product_new")
|
||||
|
||||
};
|
||||
|
||||
|
||||
function cmd_delete_product_click(id, e, node){
|
||||
|
||||
webix.message({type:"success", text: "OK Delete"});
|
||||
|
||||
};
|
||||
|
||||
|
||||
function cmd_save_product_click(id, e, node){
|
||||
var form = this.getFormView();
|
||||
|
||||
if (!form.validate()) {
|
||||
webix.message({ type:"error", text:"Valores inválidos" });
|
||||
return
|
||||
}
|
||||
|
||||
$$('form_product').clear();
|
||||
$$("multi_products").setValue("products_home")
|
||||
webix.message({type:"success", text: "Producto guardado correctamente"});
|
||||
|
||||
};
|
||||
|
||||
|
||||
function cmd_cancel_product_click(id, e, node){
|
||||
|
||||
$$("multi_products").setValue("products_home")
|
||||
|
||||
};
|
|
@ -0,0 +1,64 @@
|
|||
|
||||
|
||||
function validate_rfc(value){
|
||||
rfc = value.trim().toUpperCase();
|
||||
if ( rfc == ""){
|
||||
webix.message({ type:"error", text:"El RFC no puede estar vacío" });
|
||||
return false
|
||||
}
|
||||
|
||||
if (rfc.length < 12 || rfc.length > 13){
|
||||
webix.message({ type:"error", text:"Longitud incorrecta del RFC" });
|
||||
return false
|
||||
}
|
||||
|
||||
var start = 4;
|
||||
//~ var tipo = $$("opt_tipo").getValue();
|
||||
//~ if (tipo == 1 && value.length != 13){
|
||||
//~ webix.message({ type:"error", text:"RFC debe ser de 13 caracteres" });
|
||||
//~ return false
|
||||
//~ }
|
||||
//~ if (tipo == 2 && value.length != 12){
|
||||
//~ webix.message({ type:"error", text:"RFC debe ser de 12 caracteres" });
|
||||
//~ return false
|
||||
//~ }
|
||||
//~ var tipo = 1;
|
||||
//~ if (tipo == 2){
|
||||
//~ start = 3;
|
||||
//~ }
|
||||
//~ var rfc = value.toUpperCase();
|
||||
if (rfc.length == 12){
|
||||
start = 3;
|
||||
}
|
||||
var part = rfc.slice(0, start);
|
||||
var re = new RegExp('[a-z&Ñ]{' + start + '}', 'i');
|
||||
if (!part.match(re)){
|
||||
webix.message({ type:"error", text: "El RFC tiene caractéres inválidos al inicio" });
|
||||
return false
|
||||
}
|
||||
part = rfc.slice(-3);
|
||||
re = new RegExp('[a-z0-9]{3}', 'i');
|
||||
if (!part.match(re)){
|
||||
webix.message({ type:"error", text: "El RFC tiene caractéres inválidos al final" });
|
||||
return false
|
||||
}
|
||||
|
||||
part = rfc.slice(-9, -3);
|
||||
re = new RegExp('[0-9]{6}', 'i');
|
||||
if (!part.match(re)){
|
||||
webix.message({ type:"error", text: "Fecha inválida" });
|
||||
return false
|
||||
}
|
||||
var month = parseInt(part.slice(-4, -2))
|
||||
if (month == 0 || month > 12 ){
|
||||
webix.message({ type:"error", text: "Fecha inválida" });
|
||||
return false
|
||||
}
|
||||
var day = parseInt(part.slice(-2))
|
||||
if (day == 0 || day > 31 ){
|
||||
webix.message({ type:"error", text: "Fecha inválida" });
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
};
|
|
@ -0,0 +1,26 @@
|
|||
/*Spanish (Mexico) locale*/
|
||||
webix.i18n.locales["es-MX"] = {
|
||||
groupDelimiter:",",
|
||||
groupSize:3,
|
||||
decimalDelimiter:".",
|
||||
decimalSize:2,
|
||||
dateFormat:"%d/%n/%Y",
|
||||
timeFormat:"%h:%i %a",
|
||||
longDateFormat:"%l, %d' %je '%F' %je '%Y",
|
||||
fullDateFormat:"%l, %d' %je '%F' %je '%Y %h:%i %a",
|
||||
am:["a.m.","A.M."],
|
||||
pm:["p.m.","P.M."],
|
||||
price:"${obj}",
|
||||
priceSettings:{
|
||||
groupDelimiter:",",
|
||||
groupSize:3,
|
||||
decimalDelimiter:".",
|
||||
decimalSize:2
|
||||
},
|
||||
calendar:{
|
||||
monthFull:["enero","febrero","marzo","abril","mayo","junio","julio","agosto","septiembre","octubre","noviembre","diciembre"],
|
||||
monthShort:["ene","feb","mar","abr","may","jun","jul","ago","sep","oct","nov","dic"],
|
||||
dayFull:["domingo","lunes","martes","miércoles","jueves","viernes","sábado"],
|
||||
dayShort:["dom","lun","mar","mié","jue","vie","sáb"]
|
||||
}
|
||||
};
|
|
@ -0,0 +1,26 @@
|
|||
/*Spanish locale*/
|
||||
webix.i18n.locales["es"] = {
|
||||
groupDelimiter:".",
|
||||
groupSize:3,
|
||||
decimalDelimiter:",",
|
||||
decimalSize:2,
|
||||
dateFormat:"%d/%n/%Y",
|
||||
timeFormat:"%G:%i",
|
||||
longDateFormat:"%l, %d' %je '%F' %je '%Y",
|
||||
fullDateFormat:"%l, %d' %je '%F' %je '%Y %G:%i",
|
||||
am:null,
|
||||
pm:null,
|
||||
price:"{obj} €",
|
||||
priceSettings:{
|
||||
groupDelimiter:".",
|
||||
groupSize:3,
|
||||
decimalDelimiter:",",
|
||||
decimalSize:2
|
||||
},
|
||||
calendar:{
|
||||
monthFull:["enero","febrero","marzo","abril","mayo","junio","julio","agosto","septiembre","octubre","noviembre","diciembre"],
|
||||
monthShort:["ene","feb","mar","abr","may","jun","jul","ago","sep","oct","nov","dic"],
|
||||
dayFull:["domingo","lunes","martes","miércoles","jueves","viernes","sábado"],
|
||||
dayShort:["dom","lun","mar","mié","jue","vie","sáb"]
|
||||
}
|
||||
};
|
|
@ -0,0 +1,275 @@
|
|||
webix.protoUI({
|
||||
name: "sidebar",
|
||||
defaults:{
|
||||
titleHeight: 40,
|
||||
type: "sideBar",
|
||||
activeTitle: true,
|
||||
select: true,
|
||||
scroll: false,
|
||||
collapsed: false,
|
||||
collapsedWidth: 41,
|
||||
position: "left",
|
||||
width: 250,
|
||||
mouseEventDelay: 10
|
||||
},
|
||||
$init: function(config){
|
||||
this.$ready.push(this._initSidebar);
|
||||
this.$ready.push(this._initContextMenu);
|
||||
},
|
||||
|
||||
on_context:{},
|
||||
on_mouse_move:{},
|
||||
_initSidebar: function(){
|
||||
this._fullWidth = this.config.width;
|
||||
this.attachEvent("onBeforeOpen", function(id){
|
||||
if(!this.config.multipleOpen)
|
||||
this.closeAll();
|
||||
return !this.config.collapsed;
|
||||
});
|
||||
this.attachEvent("onItemClick", function(id, ev, node){
|
||||
if(this.getPopup() && !this.getPopup().config.hidden)
|
||||
ev.showpopup = true;
|
||||
if(webix.env.touch)
|
||||
this._showPopup(id, node);
|
||||
});
|
||||
this.attachEvent("onBeforeSelect", function(id){
|
||||
if(!this.getItem(id).$count){
|
||||
var selected = this.getSelectedId();
|
||||
if(selected && id!= selected){
|
||||
var parentId = this.getParentId(selected);
|
||||
|
||||
this.removeCss(parentId, "webix_sidebar_selected");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
this.attachEvent("onAfterSelect", function(id){
|
||||
var parentId = this.getParentId(id);
|
||||
this.addCss(parentId, "webix_sidebar_selected");
|
||||
var title = this.getPopupTitle();
|
||||
|
||||
title.callEvent("onMasterSelect",[id]);
|
||||
});
|
||||
this.attachEvent("onMouseMove", function(id, ev, node){
|
||||
this._showPopup(id, node);
|
||||
});
|
||||
|
||||
if(this.config.collapsed)
|
||||
this.collapse();
|
||||
},
|
||||
_showPopup: function(id, node){
|
||||
if(this.config.collapsed){
|
||||
var popup = this.getPopup();
|
||||
|
||||
if(popup){
|
||||
var title = this.getPopupTitle();
|
||||
if(title){
|
||||
this._updateTitle(id);
|
||||
}
|
||||
var list = this.getPopupList();
|
||||
if(list){
|
||||
this._updateList(id);
|
||||
}
|
||||
var x = (this.config.position == "left"?this.config.collapsedWidth:-popup.config.width);
|
||||
popup.show(node, {x: x , y:-1});
|
||||
}
|
||||
}
|
||||
},
|
||||
_updateTitle: function(id){
|
||||
var title = this.getPopupTitle();
|
||||
title.masterId = id;
|
||||
title.parse(this.getItem(id));
|
||||
var selectedId = this.getSelectedId();
|
||||
if(selectedId && this.getParentId(selectedId) == id){
|
||||
webix.html.addCss(title.$view, "webix_sidebar_selected", true);
|
||||
}
|
||||
else{
|
||||
webix.html.removeCss(title.$view, "webix_sidebar_selected");
|
||||
}
|
||||
|
||||
if(selectedId == id){
|
||||
webix.html.addCss(title.$view, "webix_selected", true);
|
||||
}
|
||||
else{
|
||||
webix.html.removeCss(title.$view, "webix_selected");
|
||||
}
|
||||
},
|
||||
_updateList: function(id){
|
||||
var list = this.getPopupList();
|
||||
list.masterId = id;
|
||||
var selectedId = this.getSelectedId();
|
||||
var data = [].concat(webix.copy(this.data.getBranch(id)));
|
||||
list.unselect();
|
||||
if(data.length){
|
||||
list.show();
|
||||
list.data.importData(data);
|
||||
if(list.exists(selectedId))
|
||||
list.select(selectedId);
|
||||
}
|
||||
else
|
||||
list.hide();
|
||||
|
||||
},
|
||||
_initContextMenu: function(){
|
||||
var config = this.config,
|
||||
popup;
|
||||
|
||||
if(config.popup){
|
||||
popup = webix.$$(config.popup);
|
||||
}
|
||||
if(!popup){
|
||||
var dirClassName = (config.position=="left"?"webix_sidebar_popup_left":"webix_sidebar_popup_right");
|
||||
var popupConfig = {
|
||||
view:"popup",
|
||||
css: "webix_sidebar_popup "+dirClassName,
|
||||
autofit: false,
|
||||
width: this._fullWidth - this.config.collapsedWidth,
|
||||
borderless: true,
|
||||
padding:0,
|
||||
body:{
|
||||
rows:[
|
||||
{
|
||||
view: "template", borderless: true, css: "webix_sidebar_popup_title",
|
||||
template: "#value#", height: this.config.titleHeight+2,
|
||||
on:{
|
||||
onMasterSelect: function(id){
|
||||
var master = this.getTopParentView().master;
|
||||
if( master && master.getParentId(id) == this.masterId){
|
||||
webix.html.addCss(this.$view, "webix_sidebar_selected", true);
|
||||
}
|
||||
if(master.config.collapsed && master.getItem(id).$level ==1){
|
||||
webix.html.addCss(this.$view, "webix_selected", true);
|
||||
}
|
||||
}
|
||||
},
|
||||
onClick:{
|
||||
webix_template: function(){
|
||||
var id = this.masterId;
|
||||
var master = this.getTopParentView().master;
|
||||
if(!master.getItem(id).$count)
|
||||
master.select(id);
|
||||
}
|
||||
}
|
||||
},
|
||||
{ view: "list", select: true, borderless: true, css: "webix_sidebar_popup_list", autoheight: true,
|
||||
on:{
|
||||
onAfterSelect: function(id){
|
||||
this.getTopParentView().master.select(id);
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
};
|
||||
webix.extend(popupConfig, config.popup||{}, true);
|
||||
popup = webix.ui(popupConfig);
|
||||
popup.master = this;
|
||||
}
|
||||
popup.attachEvent("onBeforeShow",function(){
|
||||
return config.collapsed;
|
||||
});
|
||||
var master = this;
|
||||
var h = webix.event(document.body,"mousemove", function(e){
|
||||
var trg = e.target || e.srcElement;
|
||||
if(!popup.config.hidden && !popup.$view.contains(trg) && !master.$view.firstChild.contains(trg)){
|
||||
popup.hide();
|
||||
}
|
||||
});
|
||||
this.attachEvent("onDestruct", function(){
|
||||
if(webix.removeEvent)
|
||||
webix.removeEvent(h);
|
||||
if(popup)
|
||||
popup.destructor();
|
||||
});
|
||||
config.popupId = popup.config.id;
|
||||
},
|
||||
getPopup: function(){
|
||||
return webix.$$(this.config.popupId);
|
||||
},
|
||||
getPopupTitle: function(){
|
||||
var popup = this.getPopup();
|
||||
return popup.getBody().getChildViews()[0];
|
||||
},
|
||||
getPopupList: function(){
|
||||
var popup = this.getPopup();
|
||||
return popup.getBody().getChildViews()[1];
|
||||
},
|
||||
position_setter:function(value){
|
||||
var newPos = value;
|
||||
var oldPos = value=="left"?"right":"left";
|
||||
|
||||
webix.html.removeCss(this.$view, "webix_sidebar_"+oldPos);
|
||||
webix.html.addCss(this.$view, "webix_sidebar_"+newPos, true);
|
||||
|
||||
var popup = this.getPopup();
|
||||
if(popup){
|
||||
var popupEl = popup.$view;
|
||||
webix.html.removeCss(popupEl, "webix_sidebar_popup_"+oldPos);
|
||||
webix.html.addCss(popupEl, "webix_sidebar_popup_"+newPos, true);
|
||||
}
|
||||
return value;
|
||||
},
|
||||
collapse: function(){
|
||||
this.define("collapsed", true);
|
||||
},
|
||||
expand: function(){
|
||||
this.define("collapsed", false);
|
||||
},
|
||||
toggle: function(){
|
||||
var collapsed = !this.config.collapsed;
|
||||
this.define("collapsed", collapsed);
|
||||
},
|
||||
collapsed_setter: function(value){
|
||||
var width;
|
||||
|
||||
if(!value){
|
||||
width = this._fullWidth;
|
||||
}
|
||||
else{
|
||||
width = this.config.collapsedWidth;
|
||||
this.closeAll();
|
||||
}
|
||||
|
||||
if(!value){
|
||||
this.type.collapsed = false;
|
||||
webix.html.addCss(this.$view, "webix_sidebar_expanded", true);
|
||||
}
|
||||
else{
|
||||
this.type.collapsed = true;
|
||||
webix.html.removeCss(this.$view, "webix_sidebar_expanded");
|
||||
}
|
||||
|
||||
this.define("width",width);
|
||||
this.resize();
|
||||
|
||||
return value;
|
||||
}
|
||||
}, webix.ui.tree);
|
||||
|
||||
webix.type(webix.ui.tree, {
|
||||
name:"sideBar",
|
||||
height: "auto",
|
||||
css: "webix_sidebar",
|
||||
template: function(obj, common){
|
||||
if(common.collapsed)
|
||||
return common.icon(obj, common);
|
||||
return common.arrow(obj, common)+common.icon(obj, common) +"<span>"+obj.value+"</span>";
|
||||
},
|
||||
arrow: function(obj, common){
|
||||
var html = "";
|
||||
var open = "";
|
||||
for (var i=1; i<=obj.$level; i++){
|
||||
if (i==obj.$level && obj.$count){
|
||||
var className = "webix_sidebar_dir_icon webix_icon fa-angle-"+(obj.open?"down":"left");
|
||||
html+="<span class='"+className+"'></span>";
|
||||
}
|
||||
}
|
||||
return html;
|
||||
},
|
||||
icon:function(obj, common){
|
||||
if(obj.icon)
|
||||
return "<span class='webix_icon webix_sidebar_icon fa-"+obj.icon+"'></span>";
|
||||
return "";
|
||||
}
|
||||
});
|
|
@ -0,0 +1,129 @@
|
|||
|
||||
|
||||
var toolbar_invoices = [
|
||||
{view: "button", id: "cmd_new_invoice", label: "Nueva", type: "iconButton",
|
||||
autowidth: true, icon: "plus"},
|
||||
{view: "button", id: "cmd_edit_invoice", label: "Editar", type: "iconButton",
|
||||
autowidth: true, icon: "pencil"},
|
||||
{view: "button", id: "cmd_delete_invoice", label: "Eliminar", type: "iconButton",
|
||||
autowidth: true, icon: "minus"},
|
||||
];
|
||||
|
||||
|
||||
var grid_invoices_cols = [
|
||||
{id: "id", header:"ID", hidden:true},
|
||||
{id: "serie", header: ["Serie", {content: "selectFilter"}], adjust: "data", sort:"string"},
|
||||
{id: "folio", header: ["Folio", {content: "numberFilter"}], adjust: "data", sort:"int", css: "cell_right"},
|
||||
{id: "uuid", header: ["UUID", {content: "textFilter"}], adjust: "data", sort:"string"},
|
||||
{id: "fecha", header: ["Fecha y Hora"], adjust: "data", sort:"string"},
|
||||
{id: "tipo", header: ["Tipo", {content: "selectFilter"}], adjust: "data", sort:"string"},
|
||||
{id: "estatus", header: ["Estatus", {content: "selectFilter"}], adjust: "data", sort:"string"},
|
||||
{id: "total", header: ["Total M.N.", {content: "numberFilter"}], width: 150, sort:"int", format: webix.i18n.priceFormat, css: "cell_right"},
|
||||
{id: "partner", header: ["Razón Social", {content: "selectFilter"}], fillspace:true, sort:"string"},
|
||||
];
|
||||
|
||||
|
||||
var grid_invoices = {
|
||||
view: "datatable",
|
||||
id: "grid_invoices",
|
||||
select: "row",
|
||||
adjust: true,
|
||||
footer: true,
|
||||
resizeColumn: true,
|
||||
headermenu: true,
|
||||
columns: grid_invoices_cols,
|
||||
};
|
||||
|
||||
|
||||
var grid_details_cols = [
|
||||
{id:"id", header:"ID", hidden: true},
|
||||
{id:"key", header:{text: 'Clave', css: 'center'}, width: 100},
|
||||
{id:"description", header:{text: 'Descripción', css: 'center'}, fillspace: true},
|
||||
{id:"unidad", header:{text: 'Unidad', css: 'center'}, width: 100},
|
||||
{id:"cant", header:{text: 'Cantidad', css: 'center'}, width: 100, format: webix.i18n.priceFormat, css:'right'},
|
||||
{id:"price", header:{text: 'Valor Unitario', css: 'center'}, width: 100, format: webix.i18n.priceFormat, css:'right'},
|
||||
{id:"importe", header:{text: 'Importe', css: 'center'}, width: 150, format: webix.i18n.priceFormat, css:'right'},
|
||||
];
|
||||
|
||||
|
||||
var grid_details = {
|
||||
view: "datatable",
|
||||
id: "grid_details",
|
||||
select: "row",
|
||||
adjust: true,
|
||||
autoheight: true,
|
||||
columns: grid_details_cols,
|
||||
data: [
|
||||
{id:1, key:'001', description:'Uno', unidad:'Pieza', cant:1, price:100, importe:100},
|
||||
{id:2, key:'002', description:'Dos', unidad:'Pieza', cant:2, price:200, importe:400},
|
||||
]
|
||||
};
|
||||
|
||||
|
||||
var controls_generate = [
|
||||
{view: "text", id: "search_partner", name: "search_partner", label: "Buscar Cliente", required: true, labelPosition: "top"},
|
||||
{view: "text", id: "search_product", name: "search_product", label: "Buscar Producto", required: true, labelPosition: "top"},
|
||||
{view:"label", label:'Detalle', height:30, align:'left'},
|
||||
grid_details,
|
||||
]
|
||||
|
||||
|
||||
var controls_invoices = [
|
||||
{
|
||||
view: "tabview",
|
||||
tabbar: {options: ["Generar"]}, animate: true,
|
||||
cells: [
|
||||
{id: "Generar", rows: controls_generate},
|
||||
]
|
||||
},
|
||||
{rows: [
|
||||
{ template:"", type: "section" },
|
||||
{ margin: 10, cols: [{},
|
||||
{view: "button", id: "cmd_save_invoice", label: "Guardar" , type: "form", autowidth: true, align:"center"},
|
||||
{view: "button", id: "cmd_send_invoice", label: "Timbrar" , type: "form", autowidth: true, align:"center"},
|
||||
{view: "button", id: "cmd_cancel_invoice", label: "Cancelar" , type: "danger", autowidth: true, align:"center"},
|
||||
{}]
|
||||
},
|
||||
]}
|
||||
];
|
||||
|
||||
|
||||
var form_invoice = {
|
||||
type: "space",
|
||||
cols: [{
|
||||
view: "form",
|
||||
id: "form_invoice",
|
||||
//~ width: 800,
|
||||
complexData: true,
|
||||
elements: controls_invoices,
|
||||
//~ rules: {
|
||||
//~ description: function(value){ return value.trim() != ""; },
|
||||
//~ unidad: function(value){ return value.trim() != ""; },
|
||||
//~ price: function(value){ return value.trim() != ""; },
|
||||
//~ }
|
||||
}]
|
||||
};
|
||||
|
||||
|
||||
var multi_invoices = {
|
||||
id: "multi_invoices",
|
||||
animate: true,
|
||||
cells:[
|
||||
{id: "invoices_home", rows:[
|
||||
{view:"toolbar", elements: toolbar_invoices},
|
||||
grid_invoices,
|
||||
]},
|
||||
{id: "invoices_new", rows:[form_invoice, {}]}
|
||||
]
|
||||
};
|
||||
|
||||
|
||||
var app_invoices = {
|
||||
id: "app_invoices",
|
||||
rows:[
|
||||
{view: "template", id: "th_invoices", type: "header", template:"Administración de Facturas" },
|
||||
multi_invoices
|
||||
]
|
||||
};
|
||||
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
|
||||
|
||||
var msg_user = 'El usuario es requerido'
|
||||
var msg_pass = 'La contraseña es requerida'
|
||||
var form_controls = [
|
||||
{view: 'text', label: 'Usuario', name: 'user', labelPosition: 'top',
|
||||
required: true, invalidMessage: msg_user},
|
||||
{view: 'text', label: 'Contraseña', name: 'pass', type: 'password',
|
||||
required: true, labelPosition: 'top', invalidMessage: msg_pass},
|
||||
{margin: 10, cols:[{}, {view: 'button', value: 'Iniciar Sesión',
|
||||
click: 'validate_login', hotkey: 'enter'}, {}]}
|
||||
]
|
||||
|
||||
|
||||
var msg_header = 'Bienvenido a Empresa Libre'
|
||||
var ui_login = {
|
||||
rows: [
|
||||
{maxHeight: 50},
|
||||
{view: 'template', template: msg_header, maxHeight: 50, css: 'login_header'},
|
||||
{maxHeight: 50},
|
||||
{cols: [{}, {type: 'space', padding: 5,
|
||||
rows: [
|
||||
{view: 'template', template: 'Acceso al sistema', type: 'header'},
|
||||
{
|
||||
container: 'form_login',
|
||||
view: 'form',
|
||||
id: 'form_login',
|
||||
width: 400,
|
||||
elements: form_controls,
|
||||
rules:{
|
||||
user:function(value){ return value.trim() != '';},
|
||||
pass:function(value){ return value.trim() != '';},
|
||||
}
|
||||
},
|
||||
]}, {}, ]
|
||||
},
|
||||
]
|
||||
}
|
|
@ -0,0 +1,76 @@
|
|||
|
||||
|
||||
var menu_data = [
|
||||
{id: "app_home", icon: "dashboard", value: "Inicio"},
|
||||
{id: "app_partners", icon: "users", value: "Clientes" },
|
||||
{id: "app_products", icon: "server", value:"Productos" },
|
||||
{id: "app_invoices", icon: "cart-plus", value:"Facturas"},
|
||||
];
|
||||
|
||||
|
||||
var sidebar = {
|
||||
view: "sidebar",
|
||||
data: menu_data,
|
||||
ready:function(){
|
||||
this.select("app_home");
|
||||
this.open(this.getParentId("app_home"));
|
||||
},
|
||||
on:{
|
||||
onAfterSelect: function(id){
|
||||
$$("multi").setValue(id)
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
var multi_main = {
|
||||
id: "multi",
|
||||
animate: true,
|
||||
cells:[
|
||||
{
|
||||
id: "app_home",
|
||||
view: "template",
|
||||
template: "HOME"
|
||||
},
|
||||
app_partners,
|
||||
app_products,
|
||||
app_invoices,
|
||||
]
|
||||
};
|
||||
|
||||
|
||||
var menu_user = {
|
||||
view: 'menu',
|
||||
id: 'menu_user',
|
||||
width: 150,
|
||||
autowidth: true,
|
||||
data:[
|
||||
{id:'0', value:'User...', submenu:[{id:1, value:'Cerrar Sesión'}]},
|
||||
],
|
||||
type:{
|
||||
subsign:true,
|
||||
},
|
||||
};
|
||||
|
||||
var ui_main = {
|
||||
rows: [
|
||||
{view: "toolbar", padding:3, elements: [
|
||||
{view: "button", type: "icon", icon: "bars",
|
||||
width: 37, align: "left", css: "app_button", click: function(){
|
||||
$$("$sidebar1").toggle()
|
||||
}
|
||||
},
|
||||
{view: "label", label: "CFDI - Boveda Fiscal"},
|
||||
{},
|
||||
menu_user,
|
||||
{view: "button", type: "icon", width: 45, css: "app_button", icon: "bell-o", badge:1}
|
||||
]
|
||||
},
|
||||
{
|
||||
cols:[
|
||||
sidebar,
|
||||
multi_main,
|
||||
]
|
||||
}
|
||||
]
|
||||
};
|
|
@ -0,0 +1,131 @@
|
|||
|
||||
|
||||
var toolbar_partners = [
|
||||
{view: "button", id: "cmd_new_partner", label: "Nuevo", type: "iconButton",
|
||||
autowidth: true, icon: "user-plus"},
|
||||
{view: "button", id: "cmd_edit_partner", label: "Editar", type: "iconButton",
|
||||
autowidth: true, icon: "user"},
|
||||
{view: "button", id: "cmd_delete_partner", label: "Eliminar", type: "iconButton",
|
||||
autowidth: true, icon: "user-times"},
|
||||
];
|
||||
|
||||
|
||||
webix.ui.datafilter.rowCount = webix.extend({
|
||||
refresh:function(master, node, value){
|
||||
node.firstChild.innerHTML = master.count();
|
||||
}
|
||||
}, webix.ui.datafilter.summColumn)
|
||||
|
||||
var grid_partners_cols = [
|
||||
{ id:'index', header:'#', adjust:'data', css:'right', footer:{content:'rowCount'}},
|
||||
{ id:"id", header:"Clave", width: 75, sort: "int", css: 'right', footer:'Clientes'},
|
||||
{ id:"cia", header: ["CIA", {content: "textFilter"}], width: 100, sort:"string" },
|
||||
{ id:"rfc", header: ["RFC", {content: "textFilter"}], width: 150, sort:"string" },
|
||||
{ id:"name", header: ["Razón Social", {content: "textFilter"}], fillspace:true, sort:"string"},
|
||||
];
|
||||
|
||||
|
||||
var grid_partners = {
|
||||
view: "datatable",
|
||||
id: "grid_partners",
|
||||
select: "row",
|
||||
adjust: true,
|
||||
footer: true,
|
||||
resizeColumn: true,
|
||||
headermenu: true,
|
||||
columns: grid_partners_cols,
|
||||
on:{
|
||||
'data->onStoreUpdated':function(){
|
||||
this.data.each(function(obj, i){
|
||||
obj.index = i+1;
|
||||
})
|
||||
}
|
||||
},
|
||||
//~ onClick:{
|
||||
//~ cmd_edit_parter: cmd_edit_partner_click,
|
||||
//~ },
|
||||
}
|
||||
|
||||
|
||||
var controls_fiscales = [
|
||||
{cols:[{view:"text", id: "cia", name: "cia", label: "CIA", width: 300, required: true, invalidMessage: "CIA inválido", attributes: {maxlength: 11}},{}]},
|
||||
{cols:[{view:"text", id: "rfc", name: "rfc", label: "RFC", width: 300, required: true, invalidMessage: "RFC inválido", attributes: {maxlength: 13}},{}]},
|
||||
{view:"text", id: "name", name: "name", label: "Razón Social", required: true, invalidMessage: "La Razón Social es requerida"},
|
||||
{view:"text", id: "street", name: "street", label: "Calle"},
|
||||
{cols:[{view:"text", id: "num_ext", name: "num_ext", width: 300, label: "No Exterior"},{}]},
|
||||
{cols:[{view:"text", id: "num_int", name: "num_int", width: 300, label: "No Interior"},{}]},
|
||||
{cols:[{view:"search", id: "postal_code", name: "postal_code", width: 300, label: "C.P.", attributes: {maxlength: 5}},{}]},
|
||||
{view:"text", id: "colonia", name: "colonia", label: "Colonia"},
|
||||
{view:"text", id: "municipio", name: "municipio", label: "Municipio"},
|
||||
{view:"search", id: "state", name: "state", label: "Estado"},
|
||||
{view:"text", id:"country", name:"country", label: "País", value: "México"},
|
||||
{template:"Contacto", type:"section"},
|
||||
{view:"text", id: "contact", name: "contact", label: "Nombre"},
|
||||
{view:"text", id: "email", name: "email", label: "Correo"},
|
||||
{view:"text", id: "phone", name: "phone", label: "Teléfono"},
|
||||
]
|
||||
|
||||
|
||||
var controls_partner = [
|
||||
{
|
||||
view: "tabview",
|
||||
tabbar: {options: ["Datos Fiscales"]}, animate: true,
|
||||
cells: [
|
||||
{id: "Datos Fiscales", rows: controls_fiscales},
|
||||
]
|
||||
},
|
||||
{rows: [
|
||||
{ template:"", type: "section" },
|
||||
{ margin: 10, cols: [{},
|
||||
{view: "button", id: "cmd_save_partner", label: "Guardar" , type: "form", autowidth: true, align:"center"},
|
||||
{view: "button", id: "cmd_cancel_partner", label: "Cancelar" , type: "danger", autowidth: true, align:"center"},
|
||||
{}]
|
||||
},
|
||||
]}
|
||||
];
|
||||
|
||||
|
||||
var form_partner = {
|
||||
type: "space",
|
||||
cols: [{
|
||||
view: "form",
|
||||
id: "form_partner",
|
||||
//~ width: 600,
|
||||
complexData: true,
|
||||
elements: controls_partner,
|
||||
elementsConfig: {
|
||||
labelWidth: 130,
|
||||
labelAlign: "right"
|
||||
},
|
||||
autoheight: true,
|
||||
rules: {
|
||||
cia: function(value){ return value.trim() != ""; },
|
||||
name: function(value){ return value.trim() != ""; },
|
||||
rfc: validate_rfc,
|
||||
}
|
||||
}]
|
||||
};
|
||||
|
||||
|
||||
var multi_partners = {
|
||||
id: "multi_partners",
|
||||
animate: true,
|
||||
cells:[
|
||||
{id: "partners_home", rows:[
|
||||
{view:"toolbar", elements: toolbar_partners},
|
||||
grid_partners,
|
||||
]},
|
||||
{id: "partners_new", rows:[form_partner, {}]}
|
||||
]
|
||||
};
|
||||
|
||||
|
||||
var app_partners = {
|
||||
id: "app_partners",
|
||||
rows:[
|
||||
{view: "template", id: "th_partner", type: "header", template:"Administración de Clientes" },
|
||||
multi_partners
|
||||
]
|
||||
};
|
||||
|
||||
|
|
@ -0,0 +1,101 @@
|
|||
|
||||
|
||||
var toolbar_products = [
|
||||
{view: "button", id: "cmd_new_product", label: "Nuevo", type: "iconButton",
|
||||
autowidth: true, icon: "plus"},
|
||||
{view: "button", id: "cmd_edit_product", label: "Editar", type: "iconButton",
|
||||
autowidth: true, icon: "pencil"},
|
||||
{view: "button", id: "cmd_delete_product", label: "Eliminar", type: "iconButton",
|
||||
autowidth: true, icon: "minus"},
|
||||
];
|
||||
|
||||
|
||||
var grid_products_cols = [
|
||||
{ id:"id", header:"ID", width: 75},
|
||||
{ id:"key", header: ["Clave", {content: "textFilter"}], width: 100, sort:"string" },
|
||||
{ id:"description", header: ["Descripción", {content: "textFilter"}], fillspace:true, sort:"string" },
|
||||
{ id:"unidad", header: ["Unidad", {content: "selectFilter"}], width: 150, sort:"string" },
|
||||
{ id:"price", header: ["Precio", {content: "numberFilter"}], width: 150, sort:"int", format: webix.i18n.priceFormat, css: "cell_right" },
|
||||
];
|
||||
|
||||
|
||||
var grid_products = {
|
||||
view: "datatable",
|
||||
id: "grid_products",
|
||||
select: "row",
|
||||
adjust: true,
|
||||
footer: true,
|
||||
resizeColumn: true,
|
||||
headermenu: true,
|
||||
columns: grid_products_cols,
|
||||
//~ onClick:{
|
||||
//~ cmd_edit_parter: cmd_edit_partner_click,
|
||||
//~ },
|
||||
};
|
||||
|
||||
|
||||
var controls_generals = [
|
||||
{view: "textarea", id: "description", name: "description", height: 200, label: "Descripción", required: true, labelPosition: "top", invalidMessage: "La Descripción es requerida" },
|
||||
{cols: [{view: "text", id: "unidad", name: "unidad", label: "Unidad", width: 300, labelWidth: 130, labelAlign: "right", required: true, invalidMessage: "La Unidad es requerida" },{}]},
|
||||
{cols: [{view: "search", type: "text", id: "price", name: "price", label: "Valor Unitario", width: 300, labelWidth: 130, labelAlign: "right", required: true, icon:"calculator", invalidMessage: "Captura un valor númerico", inputAlign:"right" },{}]},
|
||||
]
|
||||
|
||||
|
||||
var controls_products = [
|
||||
{
|
||||
view: "tabview",
|
||||
tabbar: { options: ["Generales"]}, animate: true,
|
||||
cells: [
|
||||
{id: "Generales", rows: controls_generals},
|
||||
]
|
||||
},
|
||||
{rows: [
|
||||
{ template:"", type: "section" },
|
||||
{ margin: 10, cols: [{},
|
||||
{view: "button", id: "cmd_save_product", label: "Guardar" , type: "form", autowidth: true, align:"center"},
|
||||
{view: "button", id: "cmd_cancel_product", label: "Cancelar" , type: "danger", autowidth: true, align:"center"},
|
||||
{}]
|
||||
},
|
||||
]}
|
||||
];
|
||||
|
||||
|
||||
var form_product = {
|
||||
type: "space",
|
||||
cols: [{
|
||||
view: "form",
|
||||
id: "form_product",
|
||||
//~ width: 600,
|
||||
complexData: true,
|
||||
elements: controls_products,
|
||||
rules: {
|
||||
description: function(value){ return value.trim() != ""; },
|
||||
unidad: function(value){ return value.trim() != ""; },
|
||||
price: function(value){ return value.trim() != ""; },
|
||||
}
|
||||
}]
|
||||
};
|
||||
|
||||
|
||||
var multi_products = {
|
||||
id: "multi_products",
|
||||
animate: true,
|
||||
cells:[
|
||||
{id: "products_home", rows:[
|
||||
{view:"toolbar", elements: toolbar_products},
|
||||
grid_products,
|
||||
]},
|
||||
{id: "product_new", rows:[form_product, {}]}
|
||||
]
|
||||
};
|
||||
|
||||
|
||||
var app_products = {
|
||||
id: "app_products",
|
||||
rows:[
|
||||
{view: "template", id: "th_products", type: "header", template:"Administración de Productos" },
|
||||
multi_products
|
||||
]
|
||||
};
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,27 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<title>Boveda Fiscal</title>
|
||||
<meta charset="utf-8" />
|
||||
<link rel="shortcut icon" href="/static/img/favicon.png">
|
||||
<link rel="stylesheet" href="/static/css/webix.css" type="text/css">
|
||||
<link rel="stylesheet" href="/static/css/app.css" type="text/css">
|
||||
<script src="/static/js/webix_debug.js" type="text/javascript" ></script>
|
||||
<script src="/static/js/es.js" type="text/javascript" ></script>
|
||||
|
||||
<%block name="media"/>
|
||||
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<script type="text/javascript" charset="utf-8">
|
||||
webix.debug = true;
|
||||
</script>
|
||||
|
||||
<%block name="content"/>
|
||||
|
||||
</body>
|
||||
|
||||
</html>
|
|
@ -0,0 +1,39 @@
|
|||
<%inherit file="base.html"/>
|
||||
|
||||
<%block name="media">
|
||||
<script src="/static/js/ui/login.js" type="text/javascript" ></script>
|
||||
</%block>
|
||||
|
||||
<%block name="content">
|
||||
|
||||
<div id="form_login"></div>
|
||||
|
||||
<script type="text/javascript" charset="utf-8">
|
||||
|
||||
function validate_login(){
|
||||
var form = this.getFormView();
|
||||
|
||||
if (!form.validate()) {
|
||||
webix.message({ type:"error", text:"Valores inválidos" });
|
||||
return
|
||||
}
|
||||
|
||||
var values = form.getValues();
|
||||
|
||||
webix.ajax().post("/", values, function(text, data, xhr) {
|
||||
var values = data.json();
|
||||
if (values.login) {
|
||||
window.location = "/main";
|
||||
} else {
|
||||
webix.message({ type:"error", text: values.msg });
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
webix.ready(function(){
|
||||
webix.ui(ui_login);
|
||||
});
|
||||
|
||||
</script>
|
||||
|
||||
</%block>
|
|
@ -0,0 +1,16 @@
|
|||
<%inherit file="base.html"/>
|
||||
|
||||
<%block name="media">
|
||||
|
||||
</%block>
|
||||
|
||||
<%block name="content">
|
||||
|
||||
<script type="text/javascript" charset="utf-8">
|
||||
|
||||
window.location = "/";
|
||||
};
|
||||
|
||||
</script>
|
||||
|
||||
</%block>
|
|
@ -0,0 +1,36 @@
|
|||
<%inherit file="base.html"/>
|
||||
|
||||
<%block name="media">
|
||||
<link rel="stylesheet" href="/static/css/sidebar.css" type="text/css">
|
||||
<script src="/static/js/sidebar.js" type="text/javascript" ></script>
|
||||
|
||||
<script src="/static/js/controller/util.js" type="text/javascript" ></script>
|
||||
<script src="/static/js/ui/partners.js" type="text/javascript" ></script>
|
||||
<script src="/static/js/ui/products.js" type="text/javascript" ></script>
|
||||
<script src="/static/js/ui/invoices.js" type="text/javascript" ></script>
|
||||
<script src="/static/js/ui/main.js" type="text/javascript" ></script>
|
||||
|
||||
<script src="/static/js/controller/partners.js" type="text/javascript" ></script>
|
||||
<script src="/static/js/controller/products.js" type="text/javascript" ></script>
|
||||
<script src="/static/js/controller/invoices.js" type="text/javascript" ></script>
|
||||
<script src="/static/js/controller/main.js" type="text/javascript" ></script>
|
||||
|
||||
</%block>
|
||||
|
||||
<%block name="content">
|
||||
|
||||
<input type=hidden id="username" value="${username}"/>
|
||||
|
||||
<script type="text/javascript" charset="utf-8">
|
||||
|
||||
webix.ready(function(){
|
||||
webix.CustomScroll.init()
|
||||
webix.ui(ui_main);
|
||||
controllers.init();
|
||||
var user = document.getElementById("username").value;
|
||||
$$('menu_user').getMenu(0).updateItem(0, {value:user});
|
||||
});
|
||||
|
||||
</script>
|
||||
|
||||
</%block>
|
Loading…
Reference in New Issue