Commit f42fa722 authored by Nigel Kukard's avatar Nigel Kukard
Browse files

* Various database layout changes

* Added basic inventory management
* Added basic supplier management
* Purchasing, Invoicing, Suppliers and Clients modules are work in progress
parent edeff46d
......@@ -36,12 +36,15 @@ CREATE TABLE clients (
RegNumber VARCHAR(32), # Company registration number
TaxReference VARCHAR(32), # Tax reference number, VAT/GST ... etc
GLAccID BIGINT UNSIGNED NOT NULL,
ContactPerson VARCHAR(128), # Primary contact person
PRIMARY KEY (ID),
UNIQUE KEY(Ref)
UNIQUE KEY(Ref),
FOREIGN KEY (GLAccID) REFERENCES gl_accounts(ID)
);
INSERT INTO clients (Name,ContactPerson) VALUES ('TEST CLIENT 1','Joe Soap');
......@@ -115,15 +118,17 @@ CREATE TABLE suppliers (
RegNumber VARCHAR(32), # Company registration number
TaxReference VARCHAR(32), # Tax reference number, VAT/GST ... etc
GLAccID BIGINT UNSIGNED NOT NULL,
ContactPerson VARCHAR(128), # Primary contact person
PRIMARY KEY (ID),
UNIQUE KEY(Ref)
UNIQUE KEY(Ref),
FOREIGN KEY (GLAccID) REFERENCES gl_accounts(ID)
);
INSERT INTO suppliers (Name,ContactPerson) VALUES ('TEST SUPPLIER','Joe Soap');
DROP TABLE IF EXISTS supplier_addrs;
......@@ -139,8 +144,6 @@ CREATE TABLE supplier_addrs (
FOREIGN KEY (SupplierID) REFERENCES suppliers(ID)
);
INSERT INTO supplier_addrs (SupplierID,Type,Address) VALUES (1,2,'PO Box\nXXX\nYYYY\n9999');
DROP TABLE IF EXISTS supplier_phnums;
CREATE TABLE supplier_phnums (
......@@ -157,8 +160,6 @@ CREATE TABLE supplier_phnums (
FOREIGN KEY (SupplierID) REFERENCES suppliers(ID)
);
INSERT INTO supplier_phnums (SupplierID,Type,Name,PhNumber) VALUES (1,1,'Switchboard','000 555 55666');
DROP TABLE IF EXISTS supplier_email;
CREATE TABLE supplier_email (
......@@ -175,7 +176,77 @@ CREATE TABLE supplier_email (
FOREIGN KEY (SupplierID) REFERENCES suppliers(ID)
);
INSERT INTO supplier_email (SupplierID,Type,Name,Address) VALUES (1,1,'Joe soap','joe@joes.domain');
#
# P U R C H A S I N G
#
DROP TABLE IF EXISTS supplier_invoices;
CREATE TABLE supplier_invoices (
ID SERIAL,
# Our reference
InvoiceNumber VARCHAR(32),
SupplierID BIGINT UNSIGNED NOT NULL,
# This is pulled in from supplier data
PhysicalAddress TEXT NOT NULL,
ShippingAddress TEXT,
ContactNumber TEXT,
TaxReference VARCHAR(32), # Tax reference number, VAT/GST ... etc
# Invoice details
SupplierInvNum VARCHAR(32),
IssueDate DATE,
DueDate DATE,
OrderNumber VARCHAR(64),
SubTotal FLOAT, # Add up all items sold
TaxTotal FLOAT, # Add up tax of all items
InvTotal FLOAT, # SubTotal - Tax total
# Currency VARCHAR(3),
Note TEXT,
GLTransActID BIGINT UNSIGNED, # Not null if posted
PRIMARY KEY (ID),
FOREIGN KEY (SupplierID) REFERENCES suppliers(ID),
FOREIGN KEY (GLTransActID) REFERENCES gl_transactions(ID)
);
DROP TABLE IF EXISTS supplier_invoice_items;
CREATE TABLE supplier_invoice_items (
ID SERIAL,
SupplierInvoiceID BIGINT UNSIGNED NOT NULL,
InventoryID BIGINT UNSIGNED, # Item we linked to in inventory
GLAccID BIGINT UNSIGNED, # General ledger account ID
Description VARCHAR(256),
Quantity INTEGER UNSIGNED NOT NULL,
Unit VARCHAR(32),
Price FLOAT NOT NULL,
Discount FLOAT, # % discount, 0 = none
TaxTypeID BIGINT UNSIGNED NOT NULL,
TaxMode TINYINT UNSIGNED NOT NULL DEFAULT '1', /* SellPrice is 1 - including, 2 - excluding tax */
# Pulled in from tax types and calculated
TaxRate FLOAT NOT NULL,
TaxAmount FLOAT NOT NULL,
PRIMARY KEY (ID),
FOREIGN KEY (SupplierInvoiceID) REFERENCES supplier_invoices(ID),
FOREIGN KEY (InventoryID) REFERENCES inventory(ID),
FOREIGN KEY (GLAccID) REFERENCES gl_accounts(ID)
);
......@@ -203,7 +274,10 @@ CREATE TABLE inventory (
SellPrice FLOAT NOT NULL,
TaxTypeID BIGINT UNSIGNED NOT NULL,
TaxMode TINYINT UNSIGNED NOT NULL DEFAULT '1', /* SellPrice is 1 - including, 2 - excluding tax */
Discountable TINYINT NOT NULL DEFAULT '1', /* Service is discountable on invoice/to client, 1 = yes, 0 = no */
PRIMARY KEY (ID),
UNIQUE KEY (Ref),
......@@ -252,7 +326,9 @@ CREATE TABLE invoices (
DueDate DATE,
OrderNumber VARCHAR(64),
Discount FLOAT, # % discount
SubTotal FLOAT, # Add up all items sold
TaxTotal FLOAT, # Add up tax of all items
InvTotal FLOAT, # SubTotal - Tax total
# Currency VARCHAR(3),
......@@ -278,12 +354,18 @@ CREATE TABLE invoice_items (
Quantity INTEGER UNSIGNED NOT NULL,
Unit VARCHAR(32),
Price FLOAT NOT NULL,
Discount FLOAT, # % discount
Discount FLOAT, # % discount, 0 = none, NULL = not discountable
TaxTypeID BIGINT UNSIGNED NOT NULL,
TaxMode TINYINT UNSIGNED NOT NULL DEFAULT '1', /* SellPrice is 1 - including, 2 - excluding tax */
TaxRate FLOAT NOT NULL,
TaxAmount FLOAT NOT NULL,
PRIMARY KEY (ID),
FOREIGN KEY (InvoiceID) REFERENCES invoices(ID),
FOREIGN KEY (InventoryID) REFERENCES inventory(ID)
FOREIGN KEY (InventoryID) REFERENCES inventory(ID),
FOREIGN KEY (TaxTypeID) REFERENCES tax_types(ID)
);
......@@ -488,10 +570,12 @@ CREATE TABLE gl_transactions (
TransDate DATE,
Ref VARCHAR(128) NOT NULL,
Module BIGINT UNSIGNED,
Posted TINYINT NOT NULL DEFAULT '0',
PRIMARY KEY (ID),
KEY (TransDate)
);
......@@ -518,50 +602,81 @@ CREATE TABLE gl_entries (
/*
Invoice for service:
+ to debtors/ client account
- to income account
- to vat
+ to debtors/ client account
- to income account
- to vat
Paying VAT:
+ to vat
- to bank
Us Paying VAT:
+ to vat
- to bank
Purchase item:
- to creditors / supplier account
+ to stock control
+ to VAT
(add count to item)
Us Purchase item:
- to creditors / supplier account
+ to stock control
+ to VAT
(add count to item)
Paying supplier:
- to bank
+ to supplier
- to bank
+ to supplier
Invoice for product:
+ to debtors/ client account
- to income account
- to vat
- stock control (current asset)
+ cost of goods sold (expense)
+ to debtors/ client account
- to income account
- to vat
- stock control (current asset)
+ cost of goods sold (expense)
Paying us:
+ bank
- debtors / client account
+ bank
- debtors / client account
1. Credit Note
It depends on what the credit note is for:
Credit note:
If it is for inventory sent back by a client it works as follows
+ Sales
+ VAT
- Debtor
+ Stock control
- Cost of goods sold
Debit note:
If it is for discount allowed after goods was sold etc.
+ Sales
+ VAT
- Debtor
*/
2. Debit Note
You usually only process the debit note when a credit note is received
back from the supplier, but this is how it works:
+ Supplier
- Purchases / Stock Control / Expense account (depending on what it was)
- VAT
3. We charge client interest for outstanding amount, I think it would
be + debtors account, - revenue / interest income account
Correct
4. Stock is stolen? stock gets broken?
+ Loss on theft/damage of stock (Expense)
- Stock
*/
This diff is collapsed.
# Author: Nigel Kukard <nkukard@lbsd.net>
# Date: 14/02/2007
# Desc: Inventory functions
# License: GPL
package ias::client::cmdline::Inventory;
use strict;
# Exporter stuff
require Exporter;
our (@ISA,@EXPORT);
@ISA = qw(Exporter);
@EXPORT = qw(
);
use ias::client::soap;
use ias::client::reportwriter;
1;
# vim: ts=4
......@@ -5,7 +5,7 @@
package ias::client::cmdline::gl;
package ias::client::cmdline::GL;
use strict;
......@@ -17,6 +17,262 @@ our (@ISA,@EXPORT);
);
use ias::client::misc;
use ias::client::soap;
use ias::client::reportwriter;
# GL chart of accounts
sub chart
{
my ($OUT,@args) = @_;
if (@args > 0) {
return -202;
}
my $res = soapCall($OUT,"GL","getAccounts");
if (ref $res eq "ARRAY") {
print swrite(<<'END', "ID", "Ref", "Name", "FinCat");
+===========+===================+===================================================================================+======================+
| @|||||||| | @|||||||||||||||| | @|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| | @||||||||||||||||||| |
+===========+===================+===================================================================================+=======================
END
foreach my $account (@{$res}) {
print swrite(<<'END', $account->{'ID'}, $account->{'Ref'}, $account->{'Name'}, $account->{'FinCatIdentifier'} . "/" . $account->{'FinCatDescription'});
| @<<<<<<<< | @<<<<<<<<<<<<<<<< | @<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< | @<<<<<<<<<<<<<<<<<<< |
END
}
print swrite(<<'END');
+===========+===================+===================================================================================+======================+
END
} else {
print($OUT " => ERROR(gl:chart): Error $res while executing command\n");
return -1;
}
return 0;
}
# Show GL account entries
sub show
{
my ($OUT,@args) = @_;
my $parms = parseArgs(@args);
if (!defined($parms->{'accid'})) {
return -202;
}
my $detail;
$detail->{'GLAccID'} = $parms->{'accid'};
my $res = soapCall($OUT,"GL","getAccountEntries",$detail);
if (ref $res eq "ARRAY") {
print swrite(<<'END', "ID", "Date", "Ref", "Amount", "Balance");
+===========+============+=================================================================================+==============+================+
| @|||||||| | @||||||||| | @|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| | @||||||||||| | @||||||||||||| |
+===========+============+=================================================================================+==============+================+
END
# Sort data
my @sorted = sort {$a->{'TransDate'} cmp $b->{'TransDate'}} @{$res};
my $balance = Math::BigFloat->new(0);
foreach my $entry (@sorted) {
$balance->badd($entry->{'Amount'});
print swrite(<<'END', $entry->{'ID'}, $entry->{'TransDate'}, $entry->{'Ref'} ? $entry->{'Ref'} : $entry->{'TransRef'}, sprintf('%8.2f',$entry->{'Amount'}),sprintf('%8.2f',$balance));
| @<<<<<<<< | @<<<<<<<<< | @<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< | @>>>>>>>>>>> | @>>>>>>>>>>>>> |
END
}
print swrite(<<'END');
+===========+============+=================================================================================+==============+================+
END
} else {
print($OUT " => ERROR(gl:show): Error $res while executing command\n");
return -1;
}
return 0;
}
# Create transaction
sub createTransaction
{
my ($OUT,@args) = @_;
my $parms = parseArgs(@args);
if (!defined($parms->{'date'}) || !defined($parms->{'ref'})) {
return -202;
}
my $detail;
$detail->{'Date'} = $parms->{'date'};
$detail->{'Ref'} = $parms->{'ref'};
my $res = soapCall($OUT,"GL","createTransaction",$detail);
return $res;
}
# postTransaction
sub postTransaction
{
my ($OUT,@args) = @_;
my $parms = parseArgs(@args);
if (!defined($parms->{'transid'})) {
return -202;
}
my $detail;
$detail->{'GLTransActID'} = $parms->{'transid'};
my $res = soapCall($OUT,"GL","postTransaction",$detail);
if ($res == -2) {
print($OUT " => Invalid number of entries within transaction\n");
return undef;
} elsif ($res == -3) {
print($OUT " => Entries within transaction do not balance\n");
return undef;
}
return $res;
}
# Remove transaction
sub removeTransaction
{
my ($OUT,@args) = @_;
my $parms = parseArgs(@args);
if (!defined($parms->{'transid'})) {
return -202;
}
my $detail;
$detail->{'GLTransActID'} = $parms->{'transid'};
my $res = soapCall($OUT,"GL","removeTransaction",$detail);
return $res;
}
# showTransaction
sub showTransaction
{
my ($OUT,@args) = @_;
my $parms = parseArgs(@args);
if (!defined($parms->{'transid'})) {
return -202;
}
my $detail;
$detail->{'GLTransActID'} = $parms->{'transid'};
my $res = soapCall($OUT,"GL","getTransactionEntries",$detail);
if (ref $res eq "ARRAY") {
print swrite(<<'END', "ID", "GL Account", "Ref", "Amount");
+===========+===================+=========================================================================================+================+
| @|||||||| | @|||||||||||||||| | @|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| | @||||||||||||| |
+===========+===================+=========================================================================================+================+
END
my $balance = Math::BigFloat->new(0);
foreach my $entry (@{$res}) {
print swrite(<<'END', $entry->{'ID'}, $entry->{'AccRef'}, $entry->{'Ref'} ? $entry->{'Ref'} : "", sprintf('%8.4f',$entry->{'Amount'}));
| @<<<<<<<< | @<<<<<<<<<<<<<<<< | @<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< | @>>>>>>>>>>>>> |
END
$balance->badd($entry->{'Amount'});
}
print swrite(<<'END', $balance->bstr());
+===========+===================+=========================================================================================+================+
| Transaction Balance | @>>>>>>>>>>>>> |
+=========================================================================================================================+================+
END
} else {
print($OUT " => ERROR(gl:trans:show): Error $res while executing command\n");
return -1;
}
return 0;
}
# Link transaction
sub linkTransaction
{
my ($OUT,@args) = @_;
my $parms = parseArgs(@args);
if (!defined($parms->{'transid'}) || !defined($parms->{'accid'}) || !defined($parms->{'amount'})) {
return -202;
}
my $detail;
$detail->{'GLTransActID'} = $parms->{'transid'};
$detail->{'GLAccID'} = $parms->{'accid'};
$detail->{'Amount'} = $parms->{'amount'};
$detail->{'Ref'} = $parms->{'ref'};
my $res = soapCall($OUT,"GL","linkTransaction",$detail);
return $res;
}
# List transactions
sub listTransactions
{
my ($OUT,@args) = @_;
if (@args > 0) {
return -202;
}
my $res = soapCall($OUT,"GL","getTransactions");
if (ref $res eq "ARRAY") {
print swrite(<<'END', "ID", "TransDate", "Ref", "Posted");
+===========+============+========================================================================================================+========+
| @|||||||| | @||||||||| | @||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| | @||||| |
+===========+============+========================================================================================================+========+
END
foreach my $tran (@{$res}) {
print swrite(<<'END', $tran->{'ID'}, $tran->{'TransDate'}, $tran->{'Ref'}, $tran->{'Posted'});
| @<<<<<<<< | @<<<<<<<<< | @<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< | @<<<<< |
END
}
print swrite(<<'END');
+===========+============+========================================================================================================+========+
END
} else {
print($OUT " => ERROR(gl:trans:list): Error $res while executing command\n");
return -1;
}
return 0;
}
1;
......
# Author: Nigel Kukard <nkukard@lbsd.net>
# Date: 14/02/2007
# Desc: Inventory functions
# License: GPL
package ias::client::cmdline::Inventory;
use strict;
# Exporter stuff
require Exporter;
our (@ISA,@EXPORT);
@ISA = qw(Exporter);
@EXPORT = qw(
);
use ias::client::misc;
use ias::client::soap;
use ias::client::reportwriter;