Diseño de base de datos - motor de aplicaciones de google

Estoy trabajando con el motor de aplicaciones de Google y estoy usando la API de Java Leval baja para acceder a Big Table. Estoy creando una aplicación SAAS con 4 capas:

Navegador web del clienteCapa de recursos RESTfulCapa empresarialCapa de acceso a datos

Estoy creando una aplicación para ayudar a administrar mi compañía de auto-detallado móvil (y otras similares). Tengo que representar estos cuatro conceptos separados, pero no estoy seguro de si mi plan actual es bueno:

EquipoArtículos de líneaFacturasPagos

Cita: Una "Cita" es un lugar y un tiempo en el que se espera que los empleados estén para prestar un servicio.

Elemento en linea: Un "elemento de línea" es un servicio, tarifa o descuento y su información asociada. Un ejemplo de líneas de pedido que pueden ir a una cita:

Name:                          Price: Commission: Time estimate   
Full Detail, Regular Size:        160       75       3.5 hours 
$10 Off Full Detail Coupon:       -10        0         0 hours 
Premium Detail:                   220      110       4.5 hours 
Derived totals(not a line item): $370     $185       8.0 hours

Factura: Una "Factura" es un registro de una o más líneas de pedido que un cliente se ha comprometido a pagar.

Pago: Un "pago" es un registro de los pagos que ingresaron.

En una implementación anterior de esta aplicación, la vida era más simple y traté los cuatro conceptos como una tabla en una base de datos SQL: "Cita". Una "Cita" podría tener múltiples líneas de pedido, múltiples pagos y una sola factura. La factura era solo un correo electrónico o una impresión que se produjo a partir de las líneas de pedido y el registro del cliente.

9 de cada 10 veces, esto funcionó bien. Cuando un cliente hizo una cita para uno o unos pocos vehículos y pagó por ellos mismos, todo fue grandioso. Pero este sistema no funcionó en muchas condiciones. Por ejemplo:

Cuando un cliente hizo una cita, pero la cita se agotó a mitad de camino, lo que provocó que el detallista h, y volviera al día siguiente, necesitaba dos citas, pero solo una línea, una factura y un pago.Cuando un grupo de clientes en una oficina decidieron que les hicieran sus autos el mismo día para obtener un descuento, necesitaba una cita, pero varias facturas y múltiples pagos.Cuando un cliente pagaba dos citas con un cheque, necesitaba dos citas, pero solo una factura y un pago.

Pude manejar todos estos valores atípicos esquivando un poco las cosas. Por ejemplo, si un detallista tuviera que regresar al día siguiente, simplemente haría otra cita el segundo día con una línea de pedido que dijera "Finalizar" y el costo sería de $ 0. O si un cliente pagara por dos citas con un cheque, pondría registros de pagos divididos en cada cita. El problema con esto es que crea una gran oportunidad para la congruencia de datos. La congruencia de datos puede ser un problema grave, especialmente para casos que involucran información financiera, como el tercer ejemplo en el que el cliente pagó dos citas con un cheque. Los pagos deben coincidir directamente con los bienes y servicios prestados para realizar un seguimiento adecuado de las cuentas por cobrar.

Estructura propuesta:

A continuación, se muestra una estructura normalizada para organizar y almacenar estos datos. Quizás debido a mi inexperiencia, pongo mucho énfasis en la normalización de datos porque parece una excelente manera de evitar errores de incongruencia de datos. Con esta estructura, los cambios en los datos se pueden hacer con una operación sin tener que preocuparse por actualizar otras tablas. Sin embargo, las lecturas pueden requerir múltiples lecturas junto con la organización de datos en memoria. Más adelante, si hay problemas de rendimiento, puedo agregar algunos campos desnormalizados a "Cita" para realizar consultas más rápidas y mantener intacta la estructura normalizada "segura". La desnormalización podría ralentizar las escrituras, pero estaba pensando que podría realizar llamadas asincrónicas a otros recursos o agregarlas a la tarea para que el cliente no tenga que esperar las escrituras adicionales que actualizan las partes desnormalizadas de los datos .

Mesas:

Appointment
 start_time
 etc...

Invoice
 due_date
 etc...

Payment
 invoice_Key_List
 amount_paid
 etc...

Line_Item
 appointment_Key_List
 invoice_Key
 name
 price
 etc...

La siguiente es la serie de consultas y operaciones requeridas para vincular las cuatro entidades (tablas) juntas para una lista dada de citas. Esto incluiría información sobre qué servicios se programaron para cada cita, el costo total de cada cita y el clima o no el pago recibido por cada cita. Esta sería una consulta común al cargar el calendario para la programación de citas o para que un gerente obtenga una vista general de las operaciones.

CONSULTA para la lista de "Citas" cuyo campo "start_time" se encuentra entre el rango dado.Agregue cada clave de las citas devueltas en una Lista.CONSULTA para todos los campos "Line_Items" cuyo nombre_clave_clave incluye cualquiera de las citas de devoluciónAgregue cada invoice_key de todas las líneas de pedido en una colección Set.CONSULTA para todas las "Facturas" en el conjunto de facturas (esto se puede hacer en una operación asincrónica usando el motor de la aplicación)Agregue cada clave de las facturas devueltas a una ListaCONSULTA para todos los "Pagos" cuyo campo invoice_key_list contiene una clave que coincide con cualquiera de las facturas devueltasReorganícelo en la memoria para que cada cita refleje los elementos de línea que están programados, el precio total, el tiempo estimado total y el clima o no.

... Como puede ver, esta operación requiere 4 consultas del almacén de datos, así como una organización en memoria (con suerte, la memoria será bastante rápida)

¿Alguien puede comentar sobre este diseño? Esto es lo mejor que se me ocurrió, pero sospecho que podría haber mejores opciones o diseños completamente diferentes que no creo que funcionen mejor en general o específicamente bajo las fortalezas, debilidades y capacidades de GAE (motor de aplicaciones de Google) .

¡Gracias!

Aclaracion de uso

La mayoría de las aplicaciones son más intensivas en lectura, algunas son más intensivas en escritura. A continuación, describo un caso de uso típico y operaciones de desglose que el usuario desearía realizar:

El gerente recibe una llamada de un cliente:

Leer - El administrador carga el calendario y busca un horario disponibleEscribir - El gerente consulta al cliente por su información, imaginé que esto era una sucesión de lecturas asíncronas a medida que el gerente ingresa cada información, como número de teléfono, nombre, correo electrónico, dirección, etc. O, si es necesario, tal vez uno escriba al final después de que la aplicación del cliente haya reunido toda la información y luego se envíe.Escribir - El gerente elimina la información de la tarjeta de crédito del cliente y la agrega a su registro como una operación separadaEscribir - El administrador carga la tarjeta de crédito y verifica que el pago se haya realizado

El gerente hace una llamada telefónica saliente:

Leer El gerente carga el calendarioLeer El gerente carga la cita para el cliente al que desea llamarEscribir El administrador hace clic en el botón "Llamar", se inicia una llamada y se escribe una nueva entidad CallReacordLeer El servidor de llamadas responde a la solicitud de llamada y lee CallRecord para averiguar cómo manejar la llamadaEscribir El servidor de llamadas escribe información actualizada en el CallRecordEscribir cuando la llamada está cerrada, el servidor de llamadas realiza otra solicitud al servidor para actualizar el recurso CallRecord (nota: esta solicitud no es crítica)

Respuesta aceptada :: Las dos respuestas principales fueron muy atentas y apreciadas. Acepté el que tenía pocos votos para igualar imperfectamente su exposición tanto como sea posible.

Respuestas a la pregunta(3)

Su respuesta a la pregunta