Generando Facturas y Rastreo

11

Cada 2 semanas, el sistema generará las facturas para las empresas.

La empresa recibirá una factura los días 1 y 16 cada mes. (Se ejecutará a través de Cron Job cada 2 semanas. Se escanea a través de la tabla de pedidos y luego se agrega a la tabla de 'facturas'. ¿Hay alguna alternativa?)

Hay una lista de pedidos de clientes en la orderstabla y también indica a qué compañía pertenece ( orders.company_id)

La invoicetabla calcula el costo total de los pedidos de la orderstabla.

Estoy tratando de descubrir cómo diseñar un seguimiento razonable de las facturas. Compañía en algún momento tendrá que me mandan los cánones o en algún momento les mandan los cánones ( invoice.amount)

Necesito rastrear las facturas con lo siguiente:

  • cuando la empresa me ha enviado la cantidad
  • ¿Cuándo envié el monto a la empresa?
  • cuánto ha recibido la empresa
  • ¿Cuánto le envié a la empresa?
  • ¿Recibí la cantidad completa (si no, ¿qué necesito actualizar en el Db?)
  • estado de la factura (Factura enviada, cancelada, cantidad recibida, cantidad enviada)

Aquí está el diseño de la base de datos que se me ocurrió:

mesa de la empresa

mysql> select * from company;
+----+-----------+
| id | name      |
+----+-----------+
|  1 | Company A |
|  2 | Company B |
+----+-----------+

Los clientes pueden seleccionar una empresa de mi sitio web.

tabla de pedidos

mysql> select * from orders;
+----+---------+------------+------------+---------------------+-----------+
| id | user_id | company_id | total_cost | order_date          | status_id |
+----+---------+------------+------------+---------------------+-----------+
|  1 |       5 |          2 |      25.00 | 2012-02-03 23:30:24 |         1 |
|  2 |       7 |          2 |      30.00 | 2012-02-13 18:06:12 |         1 |
+----+---------+------------+------------+---------------------+-----------+

dos clientes han pedido los productos a la Compañía B ( orders.company_id = 2). Sé que los campos de pedidos no son suficientes, simplemente simplificados para ti.

tabla de pedidos_productos

mysql> select * from orders_products;
+----+----------+------------+--------------+-------+
| id | order_id | product_id | product_name | cost  |
+----+----------+------------+--------------+-------+
|  1 |        1 |         34 | Chair        | 10.00 |
|  2 |        1 |         25 | TV           | 10.00 |
|  3 |        1 |         27 | Desk         |  2.50 |
|  4 |        1 |         36 | Laptop       |  2.50 |
|  5 |        2 |         75 | PHP Book     | 25.00 |
|  6 |        2 |         74 | MySQL Book   |  5.00 |
+----+----------+------------+--------------+-------+

Lista de productos que los clientes han pedido.

tabla de factura

mysql> select * from invoice;
+----+------------+------------+---------------------+--------+-----------+
| id | company_id | invoice_no | invoice_date        | amount | status_id |
+----+------------+------------+---------------------+--------+-----------+
|  7 |          2 |        123 | 2012-02-16 23:59:59 |  55.00 |         1 |
+----+------------+------------+---------------------+--------+-----------+

Aquí es donde estoy bastante atrapado en el diseño de tablas de facturas. No estoy seguro de cómo debería hacerse. Las facturas se generarán cada 2 semanas. El resultado del ejemplo invoice.amountes 55.00 porque se ha calculado a partir de la orders.company_id = 2tabla

Si invoice.amountes -50.00 (menos), significa que la compañía deberá enviarme el monto de las tarifas.

Si invoice.amountes 50.00, significa que necesito enviarle los honorarios a la compañía.

El status_id podría ser: (1) Factura enviada, (2) Cancelada, (3) Completada

¿Necesito agregar un invoice_idcampo en la orderstabla? Actualice el orders.invoice_idcampo cuando la fila se haya insertado en la tabla 'factura'.

tabla de pago de factura

mysql> select * from invoice_payment;
+----+------------+-----------------+-------------+---------------------+---------------------+
| id | invoice_id | amount_received | amount_sent | date_received       | date_sent           |
+----+------------+-----------------+-------------+---------------------+---------------------+
|  1 |          1 |            0.00 |       55.00 | 0000-00-00 00:00:00 | 2012-02-18 22:20:53 |
+----+------------+-----------------+-------------+---------------------+---------------------+

Aquí es donde puedo rastrear y actualizar la transacción. El pago se realizará a través de BACS.

¿Es este un buen diseño de tablas o qué necesito mejorar? ¿Qué campos y tablas debo agregar?

Si la factura se ha generado y luego tengo que hacer los cambios en orders_productso orderstablas - en caso de que vuelva a calcular el invoice.amountcampo? (Usaré PHP / MySQL).

Volcado de SQL :

CREATE TABLE IF NOT EXISTS `company` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(25) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=MyISAM  DEFAULT CHARSET=latin1 AUTO_INCREMENT=3 ;

INSERT INTO `company` (`id`, `name`) VALUES
(1, 'Company A'),
(2, 'Company B');

CREATE TABLE IF NOT EXISTS `invoice` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `company_id` int(11) NOT NULL,
  `invoice_no` int(11) NOT NULL,
  `invoice_date` datetime NOT NULL,
  `amount` decimal(6,2) NOT NULL,
  `status_id` tinyint(1) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=MyISAM  DEFAULT CHARSET=latin1 AUTO_INCREMENT=8 ;


INSERT INTO `invoice` (`id`, `company_id`, `invoice_no`, `invoice_date`, `amount`, `status_id`) VALUES
(7, 2, 123, '2012-02-16 23:59:59', '55.00', 1);


CREATE TABLE IF NOT EXISTS `invoice_payment` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `invoice_id` int(11) NOT NULL,
  `amount_received` decimal(6,2) NOT NULL,
  `amount_sent` decimal(6,2) NOT NULL,
  `date_received` datetime NOT NULL,
  `date_sent` datetime NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=MyISAM  DEFAULT CHARSET=latin1 AUTO_INCREMENT=2 ;

INSERT INTO `invoice_payment` (`id`, `invoice_id`, `amount_received`, `amount_sent`, `date_received`, `date_sent`) VALUES
(1, 1, '0.00', '55.00', '0000-00-00 00:00:00', '2012-02-18 22:20:53');


CREATE TABLE IF NOT EXISTS `orders` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `user_id` int(11) NOT NULL,
  `company_id` int(11) NOT NULL,
  `total_cost` decimal(6,2) NOT NULL,
  `order_date` datetime NOT NULL,
  `status_id` int(11) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=MyISAM  DEFAULT CHARSET=latin1 AUTO_INCREMENT=3 ;


INSERT INTO `orders` (`id`, `user_id`, `company_id`, `total_cost`, `order_date`, `status_id`) VALUES
(1, 5, 2, '25.00', '2012-02-03 23:30:24', 1),
(2, 7, 2, '30.00', '2012-02-13 18:06:12', 1);


CREATE TABLE IF NOT EXISTS `orders_products` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `order_id` int(11) NOT NULL,
  `product_id` int(11) NOT NULL,
  `product_name` varchar(100) NOT NULL,
  `cost` decimal(6,2) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=MyISAM  DEFAULT CHARSET=latin1 AUTO_INCREMENT=7 ;

INSERT INTO `orders_products` (`id`, `order_id`, `product_id`, `product_name`, `cost`) VALUES
(1, 1, 34, 'Chair', '10.00'),
(2, 1, 25, 'TV', '10.00'),
(3, 1, 27, 'Desk', '2.50'),
(4, 1, 36, 'Laptop', '2.50'),
(5, 2, 75, 'PHP Book', '25.00'),
(6, 2, 74, 'MySQL Book', '5.00');

Siéntase libre de querer actualizar / agregar tablas para responder aquí.

Gracias

Vuelvo enseguida
fuente

Respuestas:

8

Coincidencia de efectivo

Este es un problema de igualación de efectivo. Puede rastrear esto en uno de dos niveles:

  • Compare las cifras facturadas con las de efectivo (algo descuidado, pero así es como la mayoría de los Sindicatos de Lloyd's lo hacen para los negocios internos, a menudo llamado informe "escrito vs. firmado")

  • Mantenga asignaciones explícitas de efectivo de los pagos en efectivo desglosados ​​por factura.

De tu pregunta, creo que quieres hacer lo último.

Por lo general, esto se hace teniendo un conjunto separado de transacciones en efectivo y una tabla puente que tiene la asignación de pagos en efectivo a las facturas. Si los valores son iguales o el pago en efectivo viene con una sola referencia de factura, puede hacer la asignación automáticamente. Si hay una relación M: M entre facturas y pagos, deberá realizar un proceso de comparación manual (hacer esto automáticamente es en realidad una variante del problema de la mochila ).

Un sistema básico de compensación de efectivo

Imagine que tiene una tabla de facturas, una tabla de pagos en efectivo y una tabla de asignación. Cuando emite una factura, configura un registro de factura en la tabla de facturas y un registro de "cuentas por cobrar" o "por pagar" en la tabla de asignaciones.

  • Factura # 1, $ 100

  • Asignación: un registro con una referencia a la factura # 1, tipo de transacción 'por cobrar' y $ 100 adeudados. No se hace referencia a un pago en efectivo en este registro.

Ahora, obtienes un pago en efectivo de $ 100

  • Pagos en efectivo (chq # 12345): $ 100

  • Asignación: un registro con una referencia a la factura n. ° 1 y número de registro 12345, tipo de transacción 'en efectivo' y -100 adeudados ($ 100 pagados).

Puede generalizar esto a una relación M: M donde obtiene múltiples pagos contra una sola factura o un pago que cubre varias facturas. Esta estructura también facilita la creación de informes de control de crédito. El informe solo necesita encontrar facturas anteriores a (digamos) 180 días que aún tengan saldos pendientes.

Aquí hay un ejemplo del esquema más un par de escenarios y una consulta de deuda antigua. Desafortunadamente, no tengo una instancia de mysql en ejecución, así que esta es para SQL Server.

-- ==============================================================
-- === CashMatch.sql ============================================
-- ==============================================================
--


-- === Invoices =================================================
--
create table Invoice (
       InvoiceID        int identity (1,1) not null
      ,InvoiceRef       varchar (20)
      ,Amount           money
      ,InvoiceDate      datetime
)
go

alter table Invoice
  add constraint PK_Invoice 
      primary key nonclustered (InvoiceID)
go


-- === Cash Payments ============================================
--
create table CashPayment (
       CashPaymentID    int identity (1,1) not null
      ,CashPaymentRef   varchar (20)
      ,Amount           money
      ,PaidDate         datetime
)
go

alter table CashPayment
  add constraint PK_CashPayment
      primary key nonclustered (CashPaymentID)
go




-- === Allocations ==============================================
--
create table Allocation (
       AllocationID       int identity (1,1) not null
      ,CashPaymentID      int  -- Note that some records are not
      ,InvoiceID          int  -- on one side.
      ,AllocatedAmount    money
      ,AllocationType     varchar (20)
      ,TransactionDate    datetime
)
go

alter table Allocation
  add constraint PK_Allocation
      primary key nonclustered (AllocationID)
go


-- ==============================================================
-- === Scenarios ================================================
-- ==============================================================
--
declare @Invoice1ID int
       ,@Invoice2ID int
       ,@PaymentID int


-- === Raise a new invoice ======================================
--
insert Invoice (InvoiceRef, Amount, InvoiceDate)
values ('001', 100, '2012-01-01')

set @Invoice1ID = @@identity

insert Allocation (
       InvoiceID
      ,AllocatedAmount
      ,TransactionDate
      ,AllocationType
) values (@Invoice1ID, 100, '2012-01-01', 'receivable')


-- === Receive a payment ========================================
--
insert CashPayment (CashPaymentRef, Amount, PaidDate)
values ('12345', 100, getdate())

set @PaymentID = @@identity

insert Allocation (
       InvoiceID
      ,CashPaymentID
      ,AllocatedAmount
      ,TransactionDate
      ,AllocationType
) values (@Invoice1ID, @PaymentID, -100, getdate(), 'paid')



-- === Raise two invoices =======================================
--
insert Invoice (InvoiceRef, Amount, InvoiceDate)
values ('002', 75, '2012-01-01')

set @Invoice1ID = @@identity

insert Allocation (
       InvoiceID
      ,AllocatedAmount
      ,TransactionDate
      ,AllocationType
) values (@Invoice1ID, 75, '2012-01-01', 'receivable')


insert Invoice (InvoiceRef, Amount, InvoiceDate)
values ('003', 75, '2012-01-01')

set @Invoice2ID = @@identity

insert Allocation (
       InvoiceID
      ,AllocatedAmount
      ,TransactionDate
      ,AllocationType
) values (@Invoice2ID, 75, '2012-01-01', 'receivable')


-- === Receive a payment ========================================
-- The payment covers one invoice in full and part of the other.
--
insert CashPayment (CashPaymentRef, Amount, PaidDate)
values ('23456', 120, getdate()) 

set @PaymentID = @@identity

insert Allocation (
       InvoiceID
      ,CashPaymentID
      ,AllocatedAmount
      ,TransactionDate
      ,AllocationType
) values (@Invoice1ID, @PaymentID, -75, getdate(), 'paid')

insert Allocation (
       InvoiceID
      ,CashPaymentID
      ,AllocatedAmount
      ,TransactionDate
      ,AllocationType
) values (@Invoice2ID, @PaymentID, -45, getdate(), 'paid')



-- === Aged debt report ========================================
--
select i.InvoiceRef
      ,sum (a.AllocatedAmount)                 as Owing
      ,datediff (dd, i.InvoiceDate, getdate()) as Age
  from Invoice i
  join Allocation a
    on a.InvoiceID = i.InvoiceID
 group by i.InvoiceRef
         ,datediff (dd, i.InvoiceDate, getdate())
having sum (a.AllocatedAmount) > 0
Preocupado por TunbridgeWells
fuente
El mío tiene tablas separadas para facturas y pagos. Podría usar una tabla común con enlace interno. La correspondencia de efectivo a menudo se implementa de esa manera en los sistemas de contabilidad.
Preocupado por
He logrado traducir su ejemplo de SQL Server a MySQL. Pasé y entendí muy bien ahora. ¿Qué sería AllocationTypesi quisiera enviar dinero al cliente? ¿Debo insertar también en la CashPaymenttabla (digamos, pagándolas a través de BACS)?
Volveré
1
Sí, desea un registro de pago en efectivo para los pagos entrantes y salientes. Los tipos de transacción reales para las transacciones de igualación de efectivo dependen de usted.
Preocupado por
1
Puede hacer coincidir las transacciones de las facturas en ambas direcciones con un único pago de liquidación si lo desea. Por ejemplo: la factura saliente por $ 100, la factura entrante por $ 50 (-50) y el saldo del pago entrante por $ 50 con las dos facturas.
Preocupado por