* enlace al sql directo en el git de documentos * enlaces y fotos directo en el git de documentos
47 KiB
Proceso minimo bajo nivel de querys ejecutados
Ospos es uns aplicacino web, por lo que muchos SQL se repiten entre cada proceso este documento sirve como guia para realizar un API bajo nivel y asi hacer un cliente web o un cliente app movil.
Los archivos completos usados para esto estan en https://gitlab.com/osposweb/osposweb/issues/43
- 1 Consultas de verificacion
- 2 Consultas de crear item
- 3 Consultas de crear customer
- 4.1 Consultas de venta en efectivo un solo pago
- 4.2 Consultas de venta a credito varios pagos
ESTE ES UN TRABAJO EN PROGRESO, puede tener cambios o errores intencionales
1 Consultas de verificaion comunes
Dato es una aplicacion web, cada vez se realiza algo es un request y este por ende implica consultas de verificacion:
session
Siempre cada vez se realiza cualquier accion realiza dos consultas de verificiacon de sesion id estos datos se emplean a nivel de php para corroborar es la activa sino lo saca:
IMPORTANTE usando php se extrae/guarda el id del usuario (en este caso id=1)
-- VERIFICACION DE SESSION INICIADA Y ACTIVA:
SELECT GET_LOCK('864b7b0304ad61d61f838f6817c045d4', 300) AS ci_session_lock
SELECT `data` FROM `ospos_sessions`
WHERE `id` = 'spf87in54i6ihjo9nks5vv6c2n8obb8q' AND `ip_address` = '127.0.0.1'
employee
El usuario que opera es el employee
y despues de validad la sesion valida este mismo,
una vez validado empieza validar sus permisos y despues sus accesos.
El sistema tiene un employee y este el unico employee es el usuario admin de id = 1.
IMPORTANTE aqui el usuario employee
id 1 es el admin y esta en el objeto session.
-- VERIFICACION DE SI ESTE USUARIO AUN ES VALIDO (pudo haberse cambiado o eliminado en el proceso)
SELECT *
FROM `ospos_employees`
JOIN `ospos_people` ON `ospos_people`.`person_id` = `ospos_employees`.`person_id`
WHERE `ospos_employees`.`person_id` = '1'
-- VERIFICACION DE PERMISOS PARA EL USUARIO ACTIVO: EL EMPLOYEE
SELECT *
FROM `ospos_grants`
WHERE `permission_id` LIKE 'customers%' ESCAPE '!' AND `person_id` = '1'
SELECT *
FROM `ospos_permissions`
WHERE `permission_id` LIKE 'customers!_%' ESCAPE '!'
-- VERIFICACION DE ACCESOS PARA EL USUARIO ACTIVO: EMPLOYEE ID 1
SELECT *
FROM `ospos_modules`
JOIN `ospos_permissions` ON `ospos_permissions`.`permission_id` = `ospos_modules`.`module_id`
JOIN `ospos_grants` ON `ospos_permissions`.`permission_id` = `ospos_grants`.`permission_id`
WHERE `person_id` = '1' AND `menu_group` IN('home', 'both') AND `sort` !=0
ORDER BY `sort` ASC
-- (OPCIONAL) VERIFICACIONES SI ESTA EN VENTA O EN INGRESO (cuadno se esta en modulo sale o return)
SELECT *
FROM `ospos_dinner_tables`
WHERE `status` =0 AND `deleted` =0
SELECT *
FROM `ospos_stock_locations`
JOIN `ospos_permissions` AS `permissions` ON `permissions`.`location_id` = `ospos_stock_locations`.`location_id`
JOIN `ospos_grants` AS `grants` ON `grants`.`permission_id` = `permissions`.`permission_id`
WHERE `person_id` = '1' AND `permissions`.`permission_id` LIKE 'sales%' ESCAPE '!' AND `deleted` =0
-- (OPCIONAL) OBTENCION DE DATOS DE EL USUARIO ACTUAL (solo si va ver sus detalles)
SELECT *
FROM `ospos_employees`
JOIN `ospos_people` ON `ospos_people`.`person_id` = `ospos_employees`.`person_id`
WHERE `ospos_employees`.`person_id` = '1'
SELECT *
FROM `ospos_people`
WHERE `person_id` = 1
-- OBTENCION DE DATOS DE CONFIGURACION DE EL SISTEMA OSPOS
SELECT *
FROM `ospos_app_config`
ORDER BY `key` ASC
-- (OPCIONAL) SE VERIFICAN SI HAY VENTAS PENDEINTES PARA EL EMPLEADO esto cuando esta en plena venta
SELECT *
FROM `ospos_stock_locations`
JOIN `ospos_permissions` AS `permissions` ON `permissions`.`location_id` = `ospos_stock_locations`.`location_id`
JOIN `ospos_grants` AS `grants` ON `grants`.`permission_id` = `permissions`.`permission_id`
WHERE `person_id` = '1' AND `permissions`.`permission_id` LIKE 'sales%' ESCAPE '!' AND `deleted` =0
customers
El cliente es el customer
y un employee
puede alterarlo si tiene permisos en el modulo de customers,
despues de validar la sesion valida este mismo, y antes de modificar usuarios sean cliente o empleados
una vez validado empieza validar sus permisos y despues sus accesos
Por lo que los querys respectivos de busqueda, el cliente usado es de id = 2
ya que como se sabe employee
y customer
son realmente partes de people
y sus id son unicos en dicha tabla, ya que el id 1 es un employee por eso el id 2 es el cliente.
El cliente tiene id 2 porque es el segundo people
creado en el sistema que solo tiene dos,
un cliente y un employee y este el unico employee es el usuario admin de id = 1.
IMPORTANTE aqui el usuario employee
id 1 es el admin y esta en el objeto session.
NOTA como employee
y customer
son "personas" sus id son unicos, derivan de person
Aqui antes de ver el detalle de el cliente "2" verifica el empleado y despeus la data del cleinte,
notese que siempre enlaza la tabla de personas people
ya que detalles como nombre y direccion
son datos comunes de ambos actores, employee
y customer
por igual:
SELECT *
FROM `ospos_employees`
JOIN `ospos_people` ON `ospos_people`.`person_id` = `ospos_employees`.`person_id`
WHERE `ospos_employees`.`person_id` = '1'
SELECT *
FROM `ospos_customers`
JOIN `ospos_people` ON `ospos_people`.`person_id` = `ospos_customers`.`person_id`
WHERE `ospos_customers`.`person_id` = 2
SELECT *
FROM `ospos_people`
WHERE `person_id` = 2
2 Consultas de creacion de item
Un item es un producto para vender, no se guarda en sesion como la venta, se inserta directo la data, cosa contraria a si es un kit de items donde primero se reunen la data y despues se realiza la insercion en la base de datos una vez la data esta armada
Datos empleados en la pantalla de items:
- Item name : item1
- Category: cat1
- Stock type: Stock
- Item type: Standard
- Supplier: none (combo box)
- Wholesale price: 10.00
- Retail price: 15.00
- Tax 1: 1 (%)
- Tax 2: 2 (%)
- Quantity stock: 100
- Receibing Quantity: 50
- Reorder level: 70
item check
Igual que otros casos realiza verificaciones primero, de locacion de stock y de existencias, esto para cuando este en pantalla de llenado de datos precarge los combo boxes de seleccion:
SELECT *
FROM `ospos_stock_locations`
JOIN `ospos_permissions` AS `permissions` ON `permissions`.`location_id` = `ospos_stock_locations`.`location_id`
JOIN `ospos_grants` AS `grants` ON `grants`.`permission_id` = `permissions`.`permission_id`
WHERE `person_id` = '1' AND `deleted` =0 LIMIT 1
SELECT *
FROM `ospos_stock_locations`
JOIN `ospos_permissions` AS `permissions` ON `permissions`.`location_id` = `ospos_stock_locations`.`location_id`
JOIN `ospos_grants` AS `grants` ON `grants`.`permission_id` = `permissions`.`permission_id`
WHERE `person_id` = '1' AND `permissions`.`permission_id` LIKE 'items%' ESCAPE '!' AND `deleted` =0
item list
Esto ocurre en la pantalla de items donde se listan los productos, antes y cuando se muestra la pantalla de llenado y su disponibilidad, se preparan los datos al pulsar el boton:
SELECT `items`.`item_id` as `item_id`, MAX(items.name) as name, MAX(items.category) as category, MAX(items.supplier_id) as supplier_id, MAX(items.item_number) as item_number, MAX(items.description) as description, MAX(items.cost_price) as cost_price, MAX(items.unit_price) as unit_price, MAX(items.reorder_level) as reorder_level, MAX(items.receiving_quantity) as receiving_quantity, MAX(items.pic_filename) as pic_filename, MAX(items.allow_alt_description) as allow_alt_description, MAX(items.is_serialized) as is_serialized, MAX(items.deleted) as deleted, MAX(items.custom1) as custom1, MAX(items.custom2) as custom2, MAX(items.custom3) as custom3, MAX(items.custom4) as custom4, MAX(items.custom5) as custom5, MAX(items.custom6) as custom6, MAX(items.custom7) as custom7, MAX(items.custom8) as custom8, MAX(items.custom9) as custom9, MAX(items.custom10) as custom10, MAX(suppliers.person_id) as person_id, MAX(suppliers.company_name) as company_name, MAX(suppliers.agency_name) as agency_name, MAX(suppliers.account_number) as account_number, MAX(suppliers.deleted) as deleted, MAX(inventory.trans_id) as trans_id, MAX(inventory.trans_items) as trans_items, MAX(inventory.trans_user) as trans_user, MAX(inventory.trans_date) as trans_date, MAX(inventory.trans_comment) as trans_comment, MAX(inventory.trans_location) as trans_location, MAX(inventory.trans_inventory) as trans_inventory, MAX(item_quantities.item_id) as qty_item_id, MAX(item_quantities.location_id) as location_id, MAX(item_quantities.quantity) as quantity
FROM `ospos_items` as `items`
LEFT JOIN `ospos_suppliers` as `suppliers` ON `suppliers`.`person_id` = `items`.`supplier_id`
JOIN `ospos_inventory` as `inventory` ON `inventory`.`trans_items` = `items`.`item_id`
JOIN `ospos_item_quantities` as `item_quantities` ON `item_quantities`.`item_id` = `items`.`item_id`
WHERE `location_id` = '1'
AND DATE_FORMAT(trans_date, "%Y-%m-%d") BETWEEN '2010-01-01' AND '2018-05-28' /* desde el dia del install hasta el dia actual*/
AND `items`.`deleted` =0
GROUP BY `items`.`item_id` LIMIT 25 /* nota como es primera pagina, 25 items por pantalla */
SELECT COUNT(DISTINCT items.item_id) as count
FROM `ospos_items` as `items`
LEFT JOIN `ospos_suppliers` as `suppliers` ON `suppliers`.`person_id` = `items`.`supplier_id`
JOIN `ospos_inventory` as `inventory` ON `inventory`.`trans_items` = `items`.`item_id`
JOIN `ospos_item_quantities` as `item_quantities` ON `item_quantities`.`item_id` = `items`.`item_id`
WHERE `location_id` = '1'
AND DATE_FORMAT(trans_date, "%Y-%m-%d") BETWEEN '2010-01-01' AND '2018-05-28' /* desde el dia del install hasta el dia actual*/
AND `items`.`deleted` =0
SELECT *
FROM `ospos_suppliers`
JOIN `ospos_people` ON `ospos_suppliers`.`person_id` = `ospos_people`.`person_id`
WHERE `deleted` =0
ORDER BY `company_name` ASC
SELECT *
FROM `ospos_stock_locations`
JOIN `ospos_permissions` AS `permissions` ON `permissions`.`location_id` = `ospos_stock_locations`.`location_id`
JOIN `ospos_grants` AS `grants` ON `grants`.`permission_id` = `permissions`.`permission_id`
WHERE `person_id` = '1' AND `permissions`.`permission_id` LIKE 'items%' ESCAPE '!' AND `deleted` =0
SELECT *
FROM `ospos_item_quantities`
WHERE `item_id` = 1 AND `location_id` = '1'
SELECT DISTINCT `category`
FROM `ospos_items`
WHERE `category` LIKE '%cat1%' ESCAPE '!' AND `deleted` =0 /* en la pantalla se uso categoria "cat" como palabra completa */
ORDER BY `category` ASC
NOTA cada vez se escribe en los campos de combo box se realizan querys ajax ejemplo el de categoria
item crear
Despues de pulsar el boton y realizar lso consultas anteriores, se llena los datos del item, al pulsar el boton de crear se inserta en db los datos:
Datos empleados se recuerdan, la pantalla de items:
- Item name : item1
- Category: cat1
- Stock type: Stock
- Item type: Standard
- Supplier: none (combo box)
- Wholesale price: 10.00
- Retail price: 15.00
- Tax 1: 1 (%)
- Tax 2: 2 (%)
- Quantity stock: 100
- Receibing Quantity: 50
- Reorder level: 70
-- INSERCION DEL NUEVO INTEM COMO TAL
INSERT INTO `ospos_items`
(
`name`, `description`, `category`, `item_type`, `stock_type`, `supplier_id`, `item_number`,
`cost_price`, `unit_price`, `reorder_level`, `receiving_quantity`, `allow_alt_description`,
`is_serialized`, `deleted`, `custom1`, `custom2`, `custom3`, `custom4`, `custom5`, `custom6`, `custom7`, `custom8`, `custom9`, `custom10`,
`tax_category_id`
)
VALUES
(
'item1', '', 'cat1', '0', '0', NULL, NULL, 10, 15, 70, 50, 0, 0, 0, '', '', '', '', '', '', '', '', '', '', ''
)
-- NO REALIZAN UN UPDATE SINO INSERT CON DELETE esto no porque no sepan sino porque usan CI el framework
-- ADEMAS PORQUE SI HAY ITEMS SIMILARES O SI EL TAX CAMBIA SEGUN ITEMS
-- por ejemplo aqui en vez de ser uno son dos, por ende vuela la ifo vieja y pone la nueva que son dos
DELETE FROM `ospos_items_taxes` WHERE `item_id` = 1
INSERT INTO `ospos_items_taxes` (`name`, `percent`, `item_id`) VALUES ('', 1, 1)
INSERT INTO `ospos_items_taxes` (`name`, `percent`, `item_id`) VALUES ('', 2, 1)
-- DESPUES ACTUALIZA LOS INVENTARIOS RESPECTO EL NUEVO ITEM
INSERT INTO `ospos_item_quantities`
(`item_id`, `location_id`, `quantity`)
VALUES
(1, '1', 100)
INSERT INTO `ospos_inventory`
(`trans_date`, `trans_items`, `trans_user`, `trans_location`, `trans_comment`, `trans_inventory`)
VALUES
('2018-05-28 08:56:59', 1, '1', '1', 'Manual Edit of Quantity', 100)
pantalla item
El archvo log sql completo y la pantalla item empleada para esta explicacion:
item create item2
Proceso similar reducido para otro item el segundo, pero usando cambios ligeros en los datos:
Datos empleados en la pantalla de items para item2:
- Item name : item2
- Category: cat2
- Stock type: Stock
- Item type: Standard
- Supplier: none (combo box)
- Wholesale price: 13.00
- Retail price: 21.00
- Tax 1: 1 (cantidad)
- Tax 2: 3 (%)
- Quantity stock: 200
- Receiving Quantity: 100
- Reorder level: 100
-- para el input combo select de suppliers en la pantalla de nuevo item que se rellena
SELECT `ospos_items`.*, `ospos_suppliers`.`company_name`
FROM `ospos_items`
LEFT JOIN `ospos_suppliers` ON `ospos_suppliers`.`person_id` = `ospos_items`.`supplier_id`
WHERE `item_id` = -1
-- inserta el item en la tabla aun no maneja los taxes ni inventario, solo iniciales
INSERT INTO `ospos_items`
(`name`, `description`, `category`, `item_type`, `stock_type`, `supplier_id`, `item_number`, `cost_price`, `unit_price`, `reorder_level`, `receiving_quantity`, `allow_alt_description`, `is_serialized`, `deleted`, `custom1`, `custom2`, `custom3`, `custom4`, `custom5`, `custom6`, `custom7`, `custom8`, `custom9`, `custom10`, `tax_category_id`)
VALUES
('item2', '', 'cat2', '0', '0', NULL, NULL, 13, 21, 100, 100, 0, 0, 0, '', '', '', '', '', '', '', '', '', '', '')
-- pudo existir un item anterior con el tax mal relacionado
DELETE FROM `ospos_items_taxes` WHERE `item_id` = 2
-- relacion de taxes, aqui el de porcentaje, el otro no se donde lo mete
INSERT INTO `ospos_items_taxes` (`name`, `percent`, `item_id`) VALUES ('', 3, 2)
-- relacion de inventarios: primero verificacion de locaciones
SELECT * FROM `ospos_stock_locations`
JOIN `ospos_permissions` AS `permissions` ON `permissions`.`location_id` = `ospos_stock_locations`.`location_id`
JOIN `ospos_grants` AS `grants` ON `grants`.`permission_id` = `permissions`.`permission_id`
WHERE `person_id` = '1' AND `permissions`.`permission_id` LIKE 'items%' ESCAPE '!' AND `deleted` =0
-- relacion de inventario: segubndo verificacion de disponibilidad
SELECT *
FROM `ospos_item_quantities`
WHERE `item_id` = 2
AND `location_id` = '1'
-- insertar relacion inventario con existencias
INSERT INTO `ospos_item_quantities` (`item_id`, `location_id`, `quantity`) VALUES (2, '1', 200)
-- insertar relacion inventario con movimientos del mismo
INSERT INTO `ospos_inventory`
(`trans_date`, `trans_items`, `trans_user`, `trans_location`, `trans_comment`, `trans_inventory`)
VALUES
('2018-05-28 14:03:01', 2, '1', '1', 'Manual Edit of Quantity', 200)
3 Consultas de creacion de customer
El customer es un usuario igual que el employee tiene caracteristicas de persona (tabla people
)
pero no tiene entrada en la tabla employee
por ende no inicia sesion.
Aqui el cliente creado resulta que es de id = 2 ya que employee
y customer
son realmente
partes derivadas de people
y sus id son unicos en dicha tabla, el nuevo customer
se crea con
el id 2 ya que el id 1 es un employee y ambos derivan de people
por eso el id 2 es el cliente.
Datos empleados en la pantalla de customer o cliente:
- Registration consent: check
- First Name: nombre
- Last Name: apellido
- Gender: M
- Email: "correo"
- Phone Number: 5555557
- Address 1: direccion1
- Address 2: direccion2
- City: ciudad
- State: estado
- Country: "repu domin"
- Comments: comentario
- Discount: 1 (%)
customer list
Es la pantalla donde entra el modulo de clientes, lista los cleintes, y despues de insertar esta es la pantalla que muestra, pero filtrando el cliente especifico acabado de crear:
No es de mayor relevancia mas que realizar un SQL directo filtrado por id.
IMPORTANTE no se entiende para que esos querys antes crear el customer si es nuevo no tiene ventas.
customer check
Igual que otros casos realiza verificaciones primero, de employee y de customer esto para cuando este en pantalla de llenado de datos precarge los combo boxes de seleccion:
-- verifica no sea uno ya borrado, como es nuevo el id es -1 antes de insertar
SELECT *
FROM `ospos_customers`
JOIN `ospos_people` ON `ospos_people`.`person_id` = `ospos_customers`.`person_id`
WHERE `ospos_customers`.`person_id` = -1 /* claro que el id antes de crear aun aqui es -1 */
-- verifica que no exista una persona, claro como es nuevo el id es -1 antes de insertar
SELECT *
FROM `ospos_people`
WHERE `person_id` = -1 /* claro que el id antes de crear aun aqui es -1 */
LIMIT 1
-- no hay documentacion de esto, aun no se enteinde este sql:
SELECT *
FROM `ospos_customers_packages`
WHERE `deleted` =0
-- se verifica si no es un cliente temporal con ventas pendientes y el cliente e fue borrado
CREATE TEMPORARY TABLE IF NOT EXISTS ospos_sales_items_temp (INDEX(sale_id))
(
SELECT
sales.sale_id AS sale_id,
AVG(sales_items.discount_percent) AS avg_discount,
SUM(sales_items.quantity_purchased) AS quantity
FROM ospos_sales AS sales
INNER JOIN ospos_sales_items AS sales_items
ON sales_items.sale_id = sales.sale_id
WHERE sales.customer_id = -1 /* claro que el id antes de crear aun aqui es -1 */
GROUP BY sale_id
)
-- se verifica que no tenga pagos relacionados con esa venta temporal
SELECT SUM(sales_payments.payment_amount) AS total, MIN(sales_payments.payment_amount) AS min, MAX(sales_payments.payment_amount) AS max, AVG(sales_payments.payment_amount) AS average, ROUND(AVG(sales_items_temp.avg_discount), 2) AS avg_discount, ROUND(SUM(sales_items_temp.quantity), 0) AS quantity
FROM `ospos_sales`
JOIN `ospos_sales_payments` AS `sales_payments` ON `ospos_sales`.`sale_id` = `sales_payments`.`sale_id`
JOIN `ospos_sales_items_temp` AS `sales_items_temp` ON `ospos_sales`.`sale_id` = `sales_items_temp`.`sale_id`
WHERE `ospos_sales`.`customer_id` = -1 /* claro que el id antes de crear aun aqui es -1 */
AND `ospos_sales`.`sale_status` =0
GROUP BY `ospos_sales`.`customer_id`
-- una ves investigado todo relacionado a ventas se borra lo temporal, el objeto esta en ram
DROP TEMPORARY TABLE IF EXISTS ospos_sales_items_temp
-- verifica que el correo sea unico
SELECT *
FROM `ospos_customers`
JOIN `ospos_people` ON `ospos_people`.`person_id` = `ospos_customers`.`person_id`
WHERE `ospos_people`.`email` = 'correo'
AND `ospos_customers`.`deleted` =0
customer create
Los querys que se ejecutan finalmente para despues volver a la pantalla de cleintes listados:
Datos empleados se recuerda los datos empleados en la pantalla de customer o cliente:
- Registration consent: check
- First Name: nombre
- Last Name: apellido
- Gender: M
- Email: "correo"
- Phone Number: 5555557
- Address 1: direccion1
- Address 2: direccion2
- City: ciudad
- State: estado
- Country: "repu domin"
- Comments: comentario
- Discount: 1 (%)
-- se ingresa la data segun lo que se ingreso en la pantalla de customer
INSERT INTO
`ospos_people`
(`first_name`, `last_name`, `gender`, `email`, `phone_number`,
`address_1`, `address_2`, `city`, `state`, `zip`, `country`, `comments`)
VALUES
('Nombre', 'Apellido', '1', 'correo', '5555557',
'direccion1', 'cireccion2', 'ciudad', 'estado', '1234', 'repu domin', 'comentario')
-- IMPORTANTISIMO: tanto el employee como el customer son "person"s
-- por ende la data de cualqueira de estos se guarda en tabla personas
-- despues segun verifica, aqui por ser customer se verifica antes insertar customer:
SELECT *
FROM `ospos_customers`
JOIN `ospos_people` ON `ospos_people`.`person_id` = `ospos_customers`.`person_id`
WHERE `ospos_customers`.`person_id` = -1 /* el id -1 es el usado antes de estar creado, este sql no se entiende */
-- insercion en tabla customer si fuera employee seria en la tabla employee
INSERT INTO
`ospos_customers`
(`consent`, `account_number`, `company_name`, `discount_percent`, `package_id`,
`taxable`, `date`, `employee_id`, `sales_tax_code`, `person_id`)
VALUES
(1, NULL, NULL, '1', NULL,
1, '2018-05-28 09:03:59', '1', '', 2)
-- se apoya en uan tabla pra ver las ventas de el cliente recien creado (si esta en modo venta)
CREATE TEMPORARY TABLE IF NOT EXISTS ospos_sales_items_temp (INDEX(sale_id))
(
SELECT
sales.sale_id AS sale_id,
AVG(sales_items.discount_percent) AS avg_discount,
SUM(sales_items.quantity_purchased) AS quantity
FROM ospos_sales AS sales
INNER JOIN ospos_sales_items AS sales_items
ON sales_items.sale_id = sales.sale_id
WHERE sales.customer_id = '2'
GROUP BY sale_id
)
-- busca las ventas del cleinte recien creado, id = 2
SELECT SUM(sales_payments.payment_amount) AS total, MIN(sales_payments.payment_amount) AS min, MAX(sales_payments.payment_amount) AS max, AVG(sales_payments.payment_amount) AS average, ROUND(AVG(sales_items_temp.avg_discount), 2) AS avg_discount, ROUND(SUM(sales_items_temp.quantity), 0) AS quantity
FROM `ospos_sales`
JOIN `ospos_sales_payments` AS `sales_payments` ON `ospos_sales`.`sale_id` = `sales_payments`.`sale_id`
JOIN `ospos_sales_items_temp` AS `sales_items_temp` ON `ospos_sales`.`sale_id` = `sales_items_temp`.`sale_id`
WHERE `ospos_sales`.`customer_id` = '2'
AND `ospos_sales`.`sale_status` =0
GROUP BY `ospos_sales`.`customer_id`
-- borra la tabla que se uso para relacionar si hay ventas
DROP TEMPORARY TABLE IF EXISTS ospos_sales_items_temp
IMPORTANTE no se entiende para que esos querys despues de crear el customer si es nuevo no tiene ventas.
pantalla customer
El archivo log sql completo y la pantalla customer empleada para esta explicacion:
4 Consultas de Ventas
La venta es un proceso enteramente realizado via programacion php, y solo se emplea la base de datos para retraer datos, solo al final es que se realiza la insercion de la venta.
La venta es realilzada y retenida siemrpe en el objeto sesion, esto aunque no es optimo es algo que se heredo desde los inicios del desarrollo porque el equipo actual no diseño esto.
Una vez completada todos los datos del objeto venta en sesion se organizan empleando
la libreria Sale_lib
y alli es que se usa el modelo y se guarda en base de datos la venta.
4.1 Consultas de venta realizada: Venta en efectivo un solo pago
Este caso especifico es el mas simple, una venta con un item y un solo pago en efectivo:
Datos empleados
- items/productos: 1
- item 1: id=1
- catidad 1,
- precio: 15,
- descuento: 1%,
- nombre: "item1" id = 1
- item 1: id=1
- cleinte/customer: 1
- id=2, "Nombre Apellido"
- pagos/payments: 1
- payment 1: cash
- monto: 15 ($)
- payment 1: cash
El log sql completo esta aqui, se explica en este documento lo mas relevante:
add item
Como todo el proceso se realiza sobre un objeto sesion el item se agrega a un objeto especial de venta cargado en el objeto sesion del empleado, por lo que los querys respectivos son solo de busqueda, el item usado es de id = 1.
NOTA: no es muy optimo usar el objeto sesion pero es algo que se heredo del sistema original.
SELECT * FROM `ospos_items`
WHERE (
`ospos_items`.`item_number` = '1' /* err no nada que ver con id,*/
/* itemnumber es el codigo item para el empleado, id es para la db caual aqui son iguales */
OR `ospos_items`.`item_id` = 1
)
AND `ospos_items`.`deleted` =0 /* ojo los items no desaparecen solo se marcan como que ya no se venden usan o tienen */
LIMIT 1
SELECT * FROM `ospos_items_taxes`
WHERE `item_id` = '1'
-- VERIFICACIONES DE DISPONIBILIDAD, el item id=1 tenia locacion id=1 por eso el sig query
SELECT * FROM `ospos_stock_locations`
WHERE `location_id` = '1'
SELECT * FROM `ospos_item_quantities`
WHERE `item_id` = '1' AND `location_id` = '1'
SELECT *
FROM `ospos_dinner_tables` /* y disponibilidad en lla feature de restaurante */
WHERE `status` =0 AND `deleted` =0
SELECT *
FROM `ospos_items_taxes`
WHERE `item_id` = '1'
add customer
Como todo el proceso se realiza sobre un objeto sesion el cliente se agrega a
un objeto especial de venta cargado en el objeto sesion del empleado,
por lo que los querys respectivos son solo de busqueda, el cliente usado es de id = 2
ya que como se sabe employee
y customer
son realmente partes de people
y sus id son unicos en dicha tabla, ya que el id 1 es un employee por eso el id 2 es el cliente.
NOTA: no es muy optimo usar el objeto sesion pero es algo que se heredo del sistema original.
-- CONSULTA que ejecuta la llamada AJAX desded el input de CUSTOMERS al escribir letra "a":
SELECT *
FROM `ospos_customers`
JOIN `ospos_people` ON `ospos_customers`.`person_id` = `ospos_people`.`person_id`
WHERE (
`first_name` LIKE '%a%' ESCAPE '!'
OR `last_name` LIKE '%a%' ESCAPE '!'
OR CONCAT(first_name, " ", last_name) LIKE '%a%' ESCAPE '!'
OR `email` LIKE '%a%' ESCAPE '!'
OR `phone_number` LIKE '%a%' ESCAPE '!'
OR `company_name` LIKE '%a%' ESCAPE '!'
)
AND `deleted` =0
ORDER BY `last_name` ASC
-- DESPUES verificaciones preparadas de pagos de los customer antes de agregar, el coincidente es id = 2
CREATE TEMPORARY TABLE IF NOT EXISTS ospos_sales_items_temp (INDEX(sale_id))
(
SELECT
sales.sale_id AS sale_id,
AVG(sales_items.discount_percent) AS avg_discount,
SUM(sales_items.quantity_purchased) AS quantity
FROM ospos_sales AS sales
INNER JOIN ospos_sales_items AS sales_items
ON sales_items.sale_id = sales.sale_id
WHERE sales.customer_id = '2'
GROUP BY sale_id
) /* creo crea una tabla temporal y relaciona los items con este customer*/
/* recordar que una vez relacionado esta venta con el cleinte, los items estan atados a dicho cleinte */
SELECT SUM(sales_payments.payment_amount) AS total, MIN(sales_payments.payment_amount) AS min, MAX(sales_payments.payment_amount) AS max, AVG(sales_payments.payment_amount) AS average, ROUND(AVG(sales_items_temp.avg_discount), 2) AS avg_discount, ROUND(SUM(sales_items_temp.quantity), 0) AS quantity
FROM `ospos_sales`
JOIN `ospos_sales_payments` AS `sales_payments` ON `ospos_sales`.`sale_id` = `sales_payments`.`sale_id`
JOIN `ospos_sales_items_temp` AS `sales_items_temp` ON `ospos_sales`.`sale_id` = `sales_items_temp`.`sale_id`
WHERE `ospos_sales`.`customer_id` = '2' /* el seleccionado tiene id 2 segun lo que se escogio del input customers */
AND `ospos_sales`.`sale_status` =0
GROUP BY `ospos_sales`.`customer_id`
DROP TEMPORARY TABLE IF EXISTS ospos_sales_items_temp /* en el anterior saca los items y despeus la borra */
-- lo que sigue es en el objeto y en sale_lib aqui ya esta relacionado el customer con la venta
add payment
Como todo el proceso se realiza sobre un objeto sesion el pago se agrega a un objeto especial de venta cargado en el objeto sesion del empleado, por lo que los querys respectivos son solo de busqueda, la venta tiene id -1 aun aqui en este punto a menos sea una venta rescatada o pendiente, lo unico que la diferencia es el id del que vende, el employee qu es aqui id = 1 y su cliente que aqui es id =2 el resto es escogido de el input combo de pagos y el objeto sesion:
NOTA: no es muy optimo usar el objeto sesion pero es algo que se heredo del sistema original.
-- IGUAL QUE CUANDO AGREGA ITEM solo que aqui no hay llamadas ajax, mismos SQL:
CREATE TEMPORARY TABLE IF NOT EXISTS ospos_sales_items_temp (INDEX(sale_id))
(
SELECT
sales.sale_id AS sale_id,
AVG(sales_items.discount_percent) AS avg_discount,
SUM(sales_items.quantity_purchased) AS quantity
FROM ospos_sales AS sales
INNER JOIN ospos_sales_items AS sales_items
ON sales_items.sale_id = sales.sale_id
WHERE sales.customer_id = '2'
GROUP BY sale_id
) /* creo crea una tabla temporal y relaciona los items con este customer*/
/* recordar que una vez relacionado esta venta con el cleinte, los items estan atados a dicho cleinte */
SELECT SUM(sales_payments.payment_amount) AS total, MIN(sales_payments.payment_amount) AS min, MAX(sales_payments.payment_amount) AS max, AVG(sales_payments.payment_amount) AS average, ROUND(AVG(sales_items_temp.avg_discount), 2) AS avg_discount, ROUND(SUM(sales_items_temp.quantity), 0) AS quantity
FROM `ospos_sales`
JOIN `ospos_sales_payments` AS `sales_payments` ON `ospos_sales`.`sale_id` = `sales_payments`.`sale_id`
JOIN `ospos_sales_items_temp` AS `sales_items_temp` ON `ospos_sales`.`sale_id` = `sales_items_temp`.`sale_id`
WHERE `ospos_sales`.`customer_id` = '2' /* el seleccionado tiene id 2 segun lo que se escogio del input customers */
AND `ospos_sales`.`sale_status` =0
GROUP BY `ospos_sales`.`customer_id`
DROP TEMPORARY TABLE IF EXISTS ospos_sales_items_temp /* en el anterior saca los items y despeus la borra */
save sale
Como todo el proceso se realiza sobre un objeto sesion todos los datos se toman de alli, un objeto especial de venta cargado en el objeto sesion del empleado actual:
NOTA: no es muy optimo usar el objeto sesion pero es algo que se heredo del sistema original.
El proceso de guardar la venta es en 3 partes, una la venta cabecera, otra los detalles y por ultimo la actualizacion de inventariado:
Datos empleados
- items/productos: 1
- item 1: id=1
- catidad 1,
- precio: 15,
- descuento: 1%,
- nombre: "item1" id = 1
- item 1: id=1
- cleinte/customer: 1
- id=2, "Nombre Apellido"
- pagos/payments: 1
- payment 1: cash
- monto: 15 ($)
- payment 1: cash
-- el primer insert es de los items y de la relacion cleinte producto
INSERT INTO `ospos_sales`
(`sale_time`, `customer_id`, `employee_id`, `comment`, `sale_status`, `invoice_number`, `quote_number`, `work_order_number`, `dinner_table_id`, `sale_type`, `exinput1`, `exinput5`)
VALUES
('2018-05-28 09:37:04', '2', '1', '', 0, NULL, NULL, NULL, NULL, 0, '0', '')
/* OJO extinput1 y extinput5 son del extension fiscal impresion local propia de osposweb */
/* NOTA no hay aqui sale id, usa la hora y fechapara relacionar con tabal transaciones mas abajo */
-- el segundo insert es de los pagos, este no tiene uno de credito, sino uno total unicamente
INSERT INTO `ospos_sales_payments`
(`sale_id`, `payment_type`, `payment_amount`)
VALUES
(1, 'Cash', 15.3)
/* OJO aqui payment_type se guarda literalmente en el idioma del locale seleccionado, nunca mezcla locales */
-- si tiene un customer asociado o se especifico el cliente, se verifica antes de el detalle de venta
SELECT *
FROM `ospos_customers`
JOIN `ospos_people` ON `ospos_people`.`person_id` = `ospos_customers`.`person_id`
WHERE `ospos_customers`.`person_id` = '2'
SELECT `ospos_items`.*, `ospos_suppliers`.`company_name`
FROM `ospos_items`
LEFT JOIN `ospos_suppliers` ON `ospos_suppliers`.`person_id` = `ospos_items`.`supplier_id`
WHERE `item_id` = '1'
/* OJO este segudo query se repite cuantos items existan en la venta relacionada */
-- inserta el detalle de la venta, los items de esta venta, aqui solo un producto vendido para esta venta
INSERT INTO `ospos_sales_items`
(`sale_id`, `item_id`, `line`, `description`, `serialnumber`, `quantity_purchased`, `discount_percent`, `item_cost_price`, `item_unit_price`, `item_location`, `print_option`)
VALUES
(1, '1', 1, '', '', 1, '1.00', '10.00', '15.00', '1', 0)
/* OJO se repite cuantos items existan en la venta relacionada */
-- otra vez actualizaciones de inventario (creo)
SELECT *
FROM `ospos_item_quantities`
WHERE `item_id` = '1'
AND `location_id` = '1'
SELECT *
FROM `ospos_item_quantities`
WHERE `item_id` = '1'
AND `location_id` = '1'
/* OJO ESTOS DOS se repite cuantos items existan en la venta relacionada */
-- AQUI REBAJA EL INVENTARIO COMO VEZ HABIA 100 (yo meti 100, y se rebajo a 99 vendio uno
UPDATE `ospos_item_quantities` SET `quantity` = 99, `item_id` = '1', `location_id` = '1'
WHERE `item_id` = '1'
AND `location_id` = '1'
/* OJO se repite pro cada query de los dos arriba */
-- esto seria el equivalente a nuestra tabla movimientos pero movimiento para detal no mayor o despachos
INSERT INTO `ospos_inventory`
(`trans_date`, `trans_items`, `trans_user`, `trans_location`, `trans_comment`, `trans_inventory`)
VALUES
('2018-05-28 09:37:04', '1', '1', '1', 'POS 1', -1)
/* OJO el trans date el el campo relacion con la venta en el primer insert tabla sales*/
-- ahora actualizaciones de impuestos y cargos por esta venta:
/* todo este combo se repite segun la cantidad de items en la venta*/
SELECT *
FROM `ospos_items_taxes`
WHERE `item_id` = '1'
/* este item id=1 tenia dos taxes configurados, por ende ejecutara dos inserts */
INSERT INTO `ospos_sales_items_taxes`
(`sale_id`, `item_id`, `line`, `name`, `percent`, `tax_type`, `rounding_code`, `cascade_tax`, `cascade_sequence`, `item_tax_amount`)
VALUES
(1, '1', 1, '', '1.000', 1, 1, 0, 0, 0.15)
INSERT INTO `ospos_sales_items_taxes`
(`sale_id`, `item_id`, `line`, `name`, `percent`, `tax_type`, `rounding_code`, `cascade_tax`, `cascade_sequence`, `item_tax_amount`)
VALUES
(1, '1', 1, '', '2.000', 1, 1, 0, 0, 0.3)
/* igual aqui segun los taxes de el item*/
INSERT INTO `ospos_sales_taxes`
(`sale_id`, `tax_type`, `tax_group`, `sale_tax_basis`, `sale_tax_amount`, `print_sequence`, `name`, `tax_rate`, `sales_tax_code`, `rounding_code`)
VALUES
(1, 1, '1% ', '14.8500', 0.15, 0, '', '1.000', '', 1)
INSERT INTO `ospos_sales_taxes`
(`sale_id`, `tax_type`, `tax_group`, `sale_tax_basis`, `sale_tax_amount`, `print_sequence`, `name`, `tax_rate`, `sales_tax_code`, `rounding_code`)
VALUES
(1, 1, '2% ', '14.8500', 0.3, 1, '', '2.000', '', 1)
/* enlaza con la feature de restaurant */
UPDATE `ospos_dinner_tables` SET `status` = 0 WHERE `dinner_table_id` IS NULL
impresion venta
La venta es el detalle de cuantos productos se llevo el cliente:
/* no usa todos los campos en la impresion sino para la logica en php */
SELECT
`sales_items`.`sale_id`,
`sales_items`.`item_id`,
`sales_items`.`description`,
`serialnumber`,
`line`,
`quantity_purchased`,
`item_cost_price`,
`item_unit_price`,
`discount_percent`,
`item_location`,
`print_option`,
`items`.
`name` as `name`,
`category`,
`item_type`,
`stock_type`
FROM `ospos_sales_items` as `sales_items`
JOIN `ospos_items` as `items`
ON `sales_items`.`item_id` = `items`.`item_id`
WHERE `sales_items`.`sale_id` = '1'
ORDER BY `line` ASC
4.2 Consultas de venta realizada: Venta dos items y dos pagos
Este caso especifico varia con dos pagos y dos items de productos y un cleitne relacionado:
Datos empleados
- items/productos: 2
- item 1: id=1
- cantidad 1,
- precio: 15,
- descuento: 1%,
- nombre: "item1" id = 1
- item 2: id=2
- cantidad 1,
- precio: 21,
- descuento: 1%,
- nombre: "item2" id = 2
- item 1: id=1
- cleinte/customer: 1
- id=2, "Nombre Apellido"
- pagos/payments: 2
- payment 1: cash
- monto: 20 ($)
- payment 2: cash
- monto: 16.75 ($)
- payment 1: cash
El log sql completo esta aqui, se explica en este documento lo mas relevante:
ospos-5-DEVEL-2-procs-min-sqls-xx-venta-id2-sql.sql
ventana de venta
add items
/* ************* AGREGAR ITEMS item 1 */
-- SE ESCRIBIO 1 EN EL INPUT DE CODIGO DE ITEM A BUSCAR:
SELECT `item_id`, `name`, `name`
FROM `ospos_items`
WHERE `deleted` =0 AND `item_type` IN(0, 2) AND `name` LIKE '%1%' ESCAPE '!'
ORDER BY `name` ASC
SELECT `item_id`, `item_number`, `name`
FROM `ospos_items`
WHERE `deleted` =0 AND `item_type` IN(0, 2) AND `item_number` LIKE '%1%' ESCAPE '!'
ORDER BY `item_number` ASC
SELECT *
FROM `ospos_item_kits`
WHERE `name` LIKE '%1%' ESCAPE '!'
ORDER BY `name` ASC
-- PARA MOSTRAR AL EMPLOYEE LO ENCONTRADO por este codigo item en el input box select
SELECT *
FROM `ospos_items`
WHERE ( `ospos_items`.`item_number` = '1' OR `ospos_items`.`item_id` = 1 ) AND `ospos_items`.`deleted` =0
LIMIT 1
SELECT *
FROM `ospos_stock_locations`
WHERE `location_id` = '1' /* porque el item encontrado se relaciona a este location */
-- disponibilidad de este, una vez enocntrado el item id 1 filtra exacto:
SELECT *
FROM `ospos_item_quantities`
WHERE `item_id` = '1' AND `location_id` = '1'
/* ************* AGREGAR ITEMS item 1 FIN */
-- AQUI YA AGREGO EL ITEM ID pero ahora actualiza la venta verificando los taxes, hay un solo item por ahora
SELECT * FROM `ospos_items_taxes` WHERE `item_id` = '1'
/* ************* AGREGAR ITEMS item 2 INI */
-- SE ESCRIBIO 2 EN EL INPUT DE CODIGO DE ITEM A BUSCAR
SELECT `item_id`, `name`, `name`
FROM `ospos_items`
WHERE `deleted` =0 AND `item_type` IN(0, 2) AND `name` LIKE '%2%' ESCAPE '!'
ORDER BY `name` ASC
SELECT `item_id`, `item_number`, `name`
FROM `ospos_items`
WHERE `deleted` =0 AND `item_type` IN(0, 2) AND `item_number` LIKE '%2%' ESCAPE '!'
ORDER BY `item_number` ASC
SELECT *
FROM `ospos_item_kits`
WHERE `name` LIKE '%2%' ESCAPE '!'
ORDER BY `name` ASC
-- PARA MOSTRAR AL EMPLOYEE LO ENCONTRADO por este codigo item
SELECT *
FROM `ospos_items`
WHERE ( `ospos_items`.`item_number` = '2' OR `ospos_items`.`item_id` = 2 ) AND `ospos_items`.`deleted` =0
LIMIT 1
SELECT *
FROM `ospos_stock_locations`
WHERE `location_id` = '1' /* porque el item id=2 tambien esta en location id=1 */
-- disponibilidad de este, una vez enocntrado el item id 2 filtra exacto:
SELECT *
FROM `ospos_item_quantities`
WHERE `item_id` = '2' AND `location_id` = '1'
/* ************* AGREGAR ITEMS item 2 INI */
-- AQUI YA AGREGO EL ITEM ID pero ahora actualiza la venta verificando los taxes, hay ahora dos items
SELECT * FROM `ospos_items_taxes` WHERE `item_id` = '1'
SELECT * FROM `ospos_items_taxes` WHERE `item_id` = '2'
customer add
-- AQUI ESCRIBE "a" PARA BUSCAR UN CUSTOMER O UN CLIENTE
SELECT *
FROM `ospos_customers`
JOIN `ospos_people` ON `ospos_customers`.`person_id` = `ospos_people`.`person_id`
WHERE (
`first_name` LIKE '%a%' ESCAPE '!'
OR `last_name` LIKE '%a%' ESCAPE '!'
OR CONCAT(first_name, " ", last_name) LIKE '%a%' ESCAPE '!'
OR `email` LIKE '%a%' ESCAPE '!'
OR `phone_number` LIKE '%a%' ESCAPE '!'
OR `company_name` LIKE '%a%' ESCAPE '!'
)
AND `deleted` =0
ORDER BY `last_name` ASC
-- AQUI YA LO MUESTRA EN EL INPUT BOX para que lo seleccione y relacione a la venta
-- CUANDO LO RELACIONA BUSCA SI ESTE TIENE VENTAS PENDIENTE DESPUES RELACIONA LOS ITEMS
-- LAS RELACIONES DE ITEM O DE PAGOS (puede que antes de relacionra cleinte ya tenga pagos)
-- SE REALIZAN EMPLEANDO TABLAS TEMPORALES de los items y de los pagos:
SELECT *
FROM `ospos_customers`
JOIN `ospos_people` ON `ospos_people`.`person_id` = `ospos_customers`.`person_id`
WHERE `ospos_customers`.`person_id` = '2'
-- crea uan tabla temporal de los items que ya estan en la venta
CREATE TEMPORARY TABLE IF NOT EXISTS ospos_sales_items_temp (INDEX(sale_id))
(
SELECT
sales.sale_id AS sale_id,
AVG(sales_items.discount_percent) AS avg_discount,
SUM(sales_items.quantity_purchased) AS quantity
FROM ospos_sales AS sales
INNER JOIN ospos_sales_items AS sales_items
ON sales_items.sale_id = sales.sale_id
WHERE sales.customer_id = '2'
GROUP BY sale_id
)
-- despues crea una tabla temporal de los pagos que ya estan en la venta
SELECT SUM(sales_payments.payment_amount) AS total, MIN(sales_payments.payment_amount) AS min, MAX(sales_payments.payment_amount) AS max, AVG(sales_payments.payment_amount) AS average, ROUND(AVG(sales_items_temp.avg_discount), 2) AS avg_discount, ROUND(SUM(sales_items_temp.quantity), 0) AS quantity
FROM `ospos_sales`
JOIN `ospos_sales_payments` AS `sales_payments` ON `ospos_sales`.`sale_id` = `sales_payments`.`sale_id`
JOIN `ospos_sales_items_temp` AS `sales_items_temp` ON `ospos_sales`.`sale_id` = `sales_items_temp`.`sale_id`
WHERE `ospos_sales`.`customer_id` = '2' AND `ospos_sales`.`sale_status` =0
GROUP BY `ospos_sales`.`customer_id`
-- borra todo esto
DROP TEMPORARY TABLE IF EXISTS ospos_sales_items_temp
-- la relacion de estos se realiza despues en el objeto sesion ya que la venta esta alli antes de insertarse
-- verifica este cleinte uan vez realacionado y busc los datoa apra presentar en pantalla
SELECT *
FROM `ospos_customers`
JOIN `ospos_people` ON `ospos_people`.`person_id` = `ospos_customers`.`person_id`
WHERE `ospos_customers`.`person_id` = '2'
payment add
no se realizan mas que verificaciones si hay respecto uan venta suspendida con el mismo cliente
sale save
/* ********* INI savado de la venta actual con dos pagos dos items un cliente ********* */
SELECT *
FROM `ospos_customers`
JOIN `ospos_people` ON `ospos_people`.`person_id` = `ospos_customers`.`person_id`
WHERE `ospos_customers`.`person_id` = '2'
-- ******* MANEJO DE PAGOS Y CABECERA DE LA VENTA SALVAR: ********
INSERT INTO `ospos_sales`
(`sale_time`, `customer_id`, `employee_id`, `comment`, `sale_status`, `invoice_number`, `quote_number`, `work_order_number`, `dinner_table_id`, `sale_type`, `exinput1`, `exinput5`)
VALUES
('2018-05-28 16:14:42', '2', '1', '', 0, NULL, NULL, NULL, NULL, 0, '0', '')
INSERT INTO `ospos_sales_payments`
(`sale_id`, `payment_type`, `payment_amount`) VALUES (2, 'Cash', 20)
INSERT INTO `ospos_sales_payments`
(`sale_id`, `payment_type`, `payment_amount`) VALUES (2, 'Debit Card', 16.71)
-- ******* MANEJO DE ITEMS ************
-- VAMOS CON EL ITEM 1 AHORA:
SELECT `ospos_items`.*, `ospos_suppliers`.`company_name`
FROM `ospos_items`
LEFT JOIN `ospos_suppliers` ON `ospos_suppliers`.`person_id` = `ospos_items`.`supplier_id`
WHERE `item_id` = '1'
-- inserta el item primero el de id=1 en el detalle de la venta:
INSERT INTO `ospos_sales_items`
(`sale_id`, `item_id`, `line`, `description`, `serialnumber`, `quantity_purchased`, `discount_percent`, `item_cost_price`, `item_unit_price`, `item_location`, `print_option`)
VALUES
(2, '1', 1, '', '', 1, '1.00', '10.00', '15.00', '1', 0)
-- manejo de existencia e inventario para el item primero de id=1:
SELECT *
FROM `ospos_item_quantities`
WHERE `item_id` = '1'
AND `location_id` = '1' /* de aqui obtiene el 99 y lo rebajara a 98 para el item id=1 */
-- actualiza el inventario para el primer item el de id=1:
UPDATE `ospos_item_quantities`
SET `quantity` = 98, `item_id` = '1', `location_id` = '1'
WHERE `item_id` = '1'AND `location_id` = '1'
-- procede a rebajar el inventario pro transaccion:
INSERT INTO `ospos_inventory`
(`trans_date`, `trans_items`, `trans_user`, `trans_location`, `trans_comment`, `trans_inventory`)
VALUES
('2018-05-28 16:14:42', '1', '1', '1', 'POS 2', -1)
-- buscamos el taxes para el primer item el de id = 1 en esta venta ya insertada:
SELECT * FROM `ospos_items_taxes` WHERE `item_id` = '1'
-- se encontro 2 taxes para el item 1 que estaba en esta venta con id = 1
INSERT INTO `ospos_sales_items_taxes`
(`sale_id`, `item_id`, `line`, `name`, `percent`, `tax_type`, `rounding_code`, `cascade_tax`, `cascade_sequence`, `item_tax_amount`)
VALUES (2, '1', 1, '', '1.000', 1, 1, 0, 0, 0.15)
INSERT INTO `ospos_sales_items_taxes`
(`sale_id`, `item_id`, `line`, `name`, `percent`, `tax_type`, `rounding_code`, `cascade_tax`, `cascade_sequence`, `item_tax_amount`)
VALUES (2, '1', 1, '', '2.000', 1, 1, 0, 0, 0.3)
-- VAMOS CON EL ITEM 2 AHORA:
SELECT `ospos_items`.*, `ospos_suppliers`.`company_name`
FROM `ospos_items`
LEFT JOIN `ospos_suppliers` ON `ospos_suppliers`.`person_id` = `ospos_items`.`supplier_id`
WHERE `item_id` = '2'
-- inserta el item segundo el de id=2 en el detalle de la venta:
INSERT INTO `ospos_sales_items`
(`sale_id`, `item_id`, `line`, `description`, `serialnumber`, `quantity_purchased`, `discount_percent`, `item_cost_price`, `item_unit_price`, `item_location`, `print_option`)
VALUES
(2, '2', 2, '', '', 1, '1.00', '13.00', '21.00', '1', 0)
-- manejo de existencia e inventario para el item segundo de id=2: de aqui obtiene 200
SELECT *
FROM `ospos_item_quantities`
WHERE `item_id` = '2' AND `location_id` = '1'
-- actualiza el inventario pero para el segundo item el de id=2 que habia 200 y ahora 199
UPDATE `ospos_item_quantities`
SET `quantity` = 199, `item_id` = '2', `location_id` = '1'
WHERE `item_id` = '2' AND `location_id` = '1'
-- procede a rebajar el inventario pro transaccion del id item 2:
INSERT INTO `ospos_inventory`
(`trans_date`, `trans_items`, `trans_user`, `trans_location`, `trans_comment`, `trans_inventory`)
VALUES
('2018-05-28 16:14:42', '2', '1', '1', 'POS 2', -1)
-- buscamos el taxes para el segundo item el de id = 2 en esta venta ya insertada:
SELECT * FROM `ospos_items_taxes` WHERE `item_id` = '2'
-- se encontro 2 taxes para el item 2 que estaba en esta venta con id = 2 pero este solo una es de porcentaje:
INSERT INTO `ospos_sales_items_taxes`
(`sale_id`, `item_id`, `line`, `name`, `percent`, `tax_type`, `rounding_code`, `cascade_tax`, `cascade_sequence`, `item_tax_amount`)
VALUES
(2, '2', 2, '', '3.000', 1, 1, 0, 0, 0.62)
INSERT INTO `ospos_sales_taxes`
(`sale_id`, `tax_type`, `tax_group`, `sale_tax_basis`, `sale_tax_amount`, `print_sequence`, `name`, `tax_rate`, `sales_tax_code`, `rounding_code`)
VALUES
(2, 1, '1% ', '14.8500', 0.15, 0, '', '1.000', '', 1)
INSERT INTO `ospos_sales_taxes`
(`sale_id`, `tax_type`, `tax_group`, `sale_tax_basis`, `sale_tax_amount`, `print_sequence`, `name`, `tax_rate`, `sales_tax_code`, `rounding_code`)
VALUES
(2, 1, '3% ', '20.7900', 0.62, 0, '', '3.000', '', 1)
INSERT INTO `ospos_sales_taxes`
(`sale_id`, `tax_type`, `tax_group`, `sale_tax_basis`, `sale_tax_amount`, `print_sequence`, `name`, `tax_rate`, `sales_tax_code`, `rounding_code`)
VALUES
(2, 1, '2% ', '14.8500', 0.3, 1, '', '2.000', '', 1)
-- ******* FIN MANEJO DE ITEMS ************
-- si es con restaurante actualiza las tablas o mesas afectadas:
UPDATE `ospos_dinner_tables` SET `status` = 0 WHERE `dinner_table_id` IS NULL
/* ******** FIN DE INSERCION Y SALVADO DE VENTA ACTUAL ********* */
Factura resultante:
poendiente resolver el bgug que no meustra la opcion sales to credit