init
This commit is contained in:
commit
287eb2f205
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
.env
|
4
.vscode/settings.json
vendored
Normal file
4
.vscode/settings.json
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
{
|
||||
"editor.tabSize": 2,
|
||||
"editor.minimap.enabled": false
|
||||
}
|
15
Makefile
Normal file
15
Makefile
Normal file
@ -0,0 +1,15 @@
|
||||
include .env
|
||||
|
||||
migrateup:
|
||||
migrate -path db/migrations -database "${DB_TYPE}://${DB_USERNAME}:${DB_PASSWORD}@${DB_HOST}:${DB_PORT}/${DB_NAME}?sslmode=disable" -verbose up
|
||||
|
||||
migratedown:
|
||||
migrate -path db/migrations -database "${DB_TYPE}://${DB_USERNAME}:${DB_PASSWORD}@${DB_HOST}:${DB_PORT}/${DB_NAME}?sslmode=disable" -verbose down
|
||||
|
||||
sqlc:
|
||||
sqlc generate
|
||||
|
||||
test:
|
||||
go test -v -cover ./...
|
||||
|
||||
.PHONY: migrateup migratedown sqlc
|
9
db/migrations/000001_init_schema.down.sql
Normal file
9
db/migrations/000001_init_schema.down.sql
Normal file
@ -0,0 +1,9 @@
|
||||
DROP TABLE IF EXISTS users;
|
||||
DROP TABLE IF EXISTS merchants;
|
||||
DROP TABLE IF EXISTS suppliers;
|
||||
DROP TABLE IF EXISTS customers;
|
||||
DROP TABLE IF EXISTS products;
|
||||
DROP TABLE IF EXISTS purchase_order;
|
||||
DROP TABLE IF EXISTS purchase_order_detail;
|
||||
DROP TABLE IF EXISTS sale_order;
|
||||
DROP TABLE IF EXISTS sale_order_detail;
|
145
db/migrations/000001_init_schema.up.sql
Normal file
145
db/migrations/000001_init_schema.up.sql
Normal file
@ -0,0 +1,145 @@
|
||||
CREATE TABLE users(
|
||||
"id" uuid default gen_random_uuid() primary key not null,
|
||||
"index_id" bigserial not null,
|
||||
"email" varchar unique not null,
|
||||
"password" varchar not null,
|
||||
"fullname" varchar,
|
||||
"created_at" timestamp default(now()),
|
||||
"updated_at" timestamp default(now())
|
||||
);
|
||||
|
||||
CREATE TABLE merchants (
|
||||
"id" uuid default gen_random_uuid() primary key not null,
|
||||
"index_id" bigserial not null,
|
||||
"name" varchar not null,
|
||||
"owner_id" uuid references "users"("id") not null,
|
||||
"created_at" timestamp default(now()),
|
||||
"updated_at" timestamp default(now())
|
||||
);
|
||||
create table suppliers (
|
||||
"id" uuid default gen_random_uuid() primary key not null,
|
||||
"index_id" bigserial not null,
|
||||
"merchant_id" uuid references "merchants"("id") not null,
|
||||
"name" varchar(100) not null,
|
||||
"detail" jsonb,
|
||||
|
||||
"created_at" timestamp default(now()),
|
||||
"updated_at" timestamp default(now())
|
||||
);
|
||||
CREATE TABLE customers (
|
||||
"id" uuid default gen_random_uuid() primary key not null,
|
||||
"index_id" bigserial not null,
|
||||
"merchant_id" uuid references "merchants"("id") not null,
|
||||
"name" varchar not null,
|
||||
"detail" jsonb,
|
||||
|
||||
"created_at" timestamp default(now()),
|
||||
"updated_at" timestamp default(now())
|
||||
);
|
||||
CREATE TABLE products (
|
||||
"id" uuid default gen_random_uuid() primary key not null,
|
||||
"merchant_id" uuid references "merchants"("id") not null,
|
||||
"index_id" bigserial not null,
|
||||
"name" varchar not null,
|
||||
"selling_price" double precision default(0::double precision) NOT NULL,
|
||||
"purchase_price" double precision default(0:: double precision) NOT NULL,
|
||||
"stock" double precision default(0::double precision) NOT NULL,
|
||||
"created_at" timestamp default(now()),
|
||||
"updated_at" timestamp default(now())
|
||||
);
|
||||
CREATE TABLE purchase_order (
|
||||
"id" uuid default gen_random_uuid() primary key not null,
|
||||
"supplier_id" uuid references "suppliers"("id") not null,
|
||||
"merchant_id" uuid references "merchants"("id") not null,
|
||||
"index_id" bigserial not null,
|
||||
"code" varchar(100),
|
||||
"is_paid" boolean not null,
|
||||
"total" double precision not null,
|
||||
"paid_nominal" double precision not null,
|
||||
"note" text,
|
||||
|
||||
"created_at" timestamp default(now()),
|
||||
"updated_at" timestamp default(now())
|
||||
);
|
||||
|
||||
CREATE TABLE purchase_order_detail (
|
||||
"id" uuid default gen_random_uuid() primary key not null,
|
||||
"index_id" bigserial not null,
|
||||
"code" text,
|
||||
"merchant_id" uuid references "merchants"("id") not null,
|
||||
"purchase_order_id" uuid references "purchase_order"("id") not null,
|
||||
"product_id" uuid references "products"("id") not null,
|
||||
"quantity" double precision not null,
|
||||
"sub_total" double precision not null,
|
||||
"product_price" double precision not null,
|
||||
|
||||
"created_at" timestamp default(now()),
|
||||
"updated_at" timestamp default(now())
|
||||
);
|
||||
CREATE TABLE sale_order (
|
||||
"id" uuid default gen_random_uuid() primary key not null,
|
||||
"index_id" bigserial not null,
|
||||
"code" text,
|
||||
"merchant_id" uuid references "merchants"("id") not null,
|
||||
"customer_id" uuid references "customers"("id"),
|
||||
"is_paid" boolean,
|
||||
"total" double precision not null,
|
||||
"paid_nominal" double precision not null,
|
||||
"note" text,
|
||||
|
||||
"created_at" timestamp default(now()),
|
||||
"updated_at" timestamp default(now())
|
||||
);
|
||||
CREATE TABLE sale_order_detail (
|
||||
"id" uuid default gen_random_uuid() primary key not null,
|
||||
"index_id" bigserial not null,
|
||||
"sale_order_id" uuid references "sale_order"("id") not null,
|
||||
"product_id" uuid references "products"("id") not null,
|
||||
"product_name" varchar not null,
|
||||
"quantity" double precision not null,
|
||||
"sub_total" double precision not null,
|
||||
"product_price" double precision not null,
|
||||
"profit" double precision not null,
|
||||
|
||||
"created_at" timestamp default(now()),
|
||||
"updated_at" timestamp default(now())
|
||||
);
|
||||
|
||||
CREATE INDEX ON "users"("index_id");
|
||||
|
||||
|
||||
|
||||
CREATE INDEX ON "merchants"("index_id");
|
||||
|
||||
|
||||
|
||||
CREATE INDEX ON "suppliers"("index_id");
|
||||
|
||||
|
||||
|
||||
CREATE INDEX ON "customers"("index_id");
|
||||
|
||||
|
||||
|
||||
CREATE INDEX ON "products" ("name");
|
||||
CREATE INDEX ON "products" ("selling_price");
|
||||
CREATE INDEX ON "products" ("index_id");
|
||||
CREATE INDEX ON "products" ("purchase_price");
|
||||
CREATE INDEX ON "products" ("stock");
|
||||
|
||||
|
||||
CREATE INDEX ON "purchase_order" ("merchant_id");
|
||||
CREATE INDEX ON "purchase_order" ("supplier_id");
|
||||
CREATE INDEX ON "purchase_order" ("index_id");
|
||||
CREATE INDEX ON "purchase_order" ("created_at");
|
||||
|
||||
|
||||
|
||||
CREATE INDEX ON "purchase_order_detail" ("index_id");
|
||||
|
||||
|
||||
CREATE INDEX ON "sale_order" ("index_id");
|
||||
|
||||
|
||||
|
||||
CREATE INDEX ON "sale_order_detail" ("index_id");
|
23
db/query/customers.sql
Normal file
23
db/query/customers.sql
Normal file
@ -0,0 +1,23 @@
|
||||
-- name: CreateCustomers :one
|
||||
INSERT INTO customers (
|
||||
merchant_id,
|
||||
name,
|
||||
detail
|
||||
) VALUES (
|
||||
$1, $2, $3
|
||||
)
|
||||
RETURNING *;
|
||||
|
||||
-- name: CustomersList :many
|
||||
SELECT * FROM customers
|
||||
WHERE merchant_id = $1
|
||||
ORDER BY index_id
|
||||
LIMIT $2
|
||||
OFFSET $3;
|
||||
|
||||
-- name: UpdateCustomer :one
|
||||
SELECT * FROM customers
|
||||
WHERE id = $1;
|
||||
|
||||
-- name: DeleteCustomer :exec
|
||||
DELETE FROM customers where id = $1;
|
8
db/query/merchant.sql
Normal file
8
db/query/merchant.sql
Normal file
@ -0,0 +1,8 @@
|
||||
-- name: GetMerchantById :one
|
||||
SELECT * FROM merchants
|
||||
WHERE id = $1;
|
||||
|
||||
-- name: GetMerchantByUserId :one
|
||||
SELECT * FROM merchants
|
||||
WHERE owner_id = $1;
|
||||
|
36
db/query/products.sql
Normal file
36
db/query/products.sql
Normal file
@ -0,0 +1,36 @@
|
||||
-- name: CreateProduct :one
|
||||
INSERT INTO products (
|
||||
merchant_id,
|
||||
name,
|
||||
selling_price,
|
||||
purchase_price,
|
||||
stock
|
||||
) VALUES (
|
||||
$1, $2, $3, $4, $5
|
||||
)
|
||||
RETURNING *;
|
||||
|
||||
-- name: UpdateProductStock :one
|
||||
UPDATE products
|
||||
SET stock = $1
|
||||
WHERE id = $2
|
||||
RETURNING stock;
|
||||
|
||||
-- name: GetProduct :one
|
||||
SELECT * FROM products
|
||||
WHERE id = $1;
|
||||
|
||||
-- name: ListProducts :many
|
||||
SELECT * FROM products
|
||||
ORDER BY index_id
|
||||
LIMIT $1
|
||||
OFFSET $2;
|
||||
|
||||
-- name: UpdateProduct :one
|
||||
UPDATE products
|
||||
SET name = $2, selling_price = $3, purchase_price = $4, stock = $5, updated_at = $6
|
||||
WHERE id = $1
|
||||
RETURNING *;
|
||||
|
||||
-- name: DeleteProduct :exec
|
||||
DELETE FROM products WHERE id = $1;
|
13
db/query/purchase_order.sql
Normal file
13
db/query/purchase_order.sql
Normal file
@ -0,0 +1,13 @@
|
||||
-- name: CreatePurchaseOrder :one
|
||||
INSERT INTO purchase_order (
|
||||
merchant_id,
|
||||
supplier_id,
|
||||
code,
|
||||
is_paid,
|
||||
total,
|
||||
paid_nominal,
|
||||
note
|
||||
) VALUES (
|
||||
$1, $2, $3, $4, $5, $6, $7
|
||||
)
|
||||
RETURNING *;
|
12
db/query/purchase_order_detail.sql
Normal file
12
db/query/purchase_order_detail.sql
Normal file
@ -0,0 +1,12 @@
|
||||
-- name: CreatePurchaseOrderDetail :one
|
||||
INSERT INTO purchase_order_detail (
|
||||
purchase_order_id,
|
||||
merchant_id,
|
||||
product_id,
|
||||
quantity,
|
||||
sub_total,
|
||||
product_price
|
||||
) VALUES (
|
||||
$1, $2, $3, $4, $5, $6
|
||||
)
|
||||
RETURNING *;
|
23
db/query/suppliers.sql
Normal file
23
db/query/suppliers.sql
Normal file
@ -0,0 +1,23 @@
|
||||
-- name: CreateSuppliers :one
|
||||
INSERT INTO suppliers (
|
||||
merchant_id,
|
||||
name,
|
||||
detail
|
||||
) VALUES (
|
||||
$1, $2, $3
|
||||
)
|
||||
RETURNING *;
|
||||
|
||||
-- name: SuppliersList :many
|
||||
SELECT * FROM suppliers
|
||||
WHERE merchant_id = $1
|
||||
ORDER BY index_id
|
||||
LIMIT $2
|
||||
OFFSET $3;
|
||||
|
||||
-- name: UpdateSupplier :one
|
||||
SELECT * FROM suppliers
|
||||
WHERE id = $1;
|
||||
|
||||
-- name: DeleteSupplier :exec
|
||||
DELETE FROM suppliers where id = $1;
|
119
db/sqlc/customers.sql.go
Normal file
119
db/sqlc/customers.sql.go
Normal file
@ -0,0 +1,119 @@
|
||||
// Code generated by sqlc. DO NOT EDIT.
|
||||
// versions:
|
||||
// sqlc v1.17.2
|
||||
// source: customers.sql
|
||||
|
||||
package db
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/google/uuid"
|
||||
"github.com/tabbed/pqtype"
|
||||
)
|
||||
|
||||
const createCustomers = `-- name: CreateCustomers :one
|
||||
INSERT INTO customers (
|
||||
merchant_id,
|
||||
name,
|
||||
detail
|
||||
) VALUES (
|
||||
$1, $2, $3
|
||||
)
|
||||
RETURNING id, index_id, merchant_id, name, detail, created_at, updated_at
|
||||
`
|
||||
|
||||
type CreateCustomersParams struct {
|
||||
MerchantID uuid.UUID `json:"merchant_id"`
|
||||
Name string `json:"name"`
|
||||
Detail pqtype.NullRawMessage `json:"detail"`
|
||||
}
|
||||
|
||||
func (q *Queries) CreateCustomers(ctx context.Context, arg CreateCustomersParams) (Customer, error) {
|
||||
row := q.db.QueryRowContext(ctx, createCustomers, arg.MerchantID, arg.Name, arg.Detail)
|
||||
var i Customer
|
||||
err := row.Scan(
|
||||
&i.ID,
|
||||
&i.IndexID,
|
||||
&i.MerchantID,
|
||||
&i.Name,
|
||||
&i.Detail,
|
||||
&i.CreatedAt,
|
||||
&i.UpdatedAt,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const customersList = `-- name: CustomersList :many
|
||||
SELECT id, index_id, merchant_id, name, detail, created_at, updated_at FROM customers
|
||||
WHERE merchant_id = $1
|
||||
ORDER BY index_id
|
||||
LIMIT $2
|
||||
OFFSET $3
|
||||
`
|
||||
|
||||
type CustomersListParams struct {
|
||||
MerchantID uuid.UUID `json:"merchant_id"`
|
||||
Limit int32 `json:"limit"`
|
||||
Offset int32 `json:"offset"`
|
||||
}
|
||||
|
||||
func (q *Queries) CustomersList(ctx context.Context, arg CustomersListParams) ([]Customer, error) {
|
||||
rows, err := q.db.QueryContext(ctx, customersList, arg.MerchantID, arg.Limit, arg.Offset)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
var items []Customer
|
||||
for rows.Next() {
|
||||
var i Customer
|
||||
if err := rows.Scan(
|
||||
&i.ID,
|
||||
&i.IndexID,
|
||||
&i.MerchantID,
|
||||
&i.Name,
|
||||
&i.Detail,
|
||||
&i.CreatedAt,
|
||||
&i.UpdatedAt,
|
||||
); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
items = append(items, i)
|
||||
}
|
||||
if err := rows.Close(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := rows.Err(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return items, nil
|
||||
}
|
||||
|
||||
const deleteCustomer = `-- name: DeleteCustomer :exec
|
||||
DELETE FROM customers where id = $1
|
||||
`
|
||||
|
||||
func (q *Queries) DeleteCustomer(ctx context.Context, id uuid.UUID) error {
|
||||
_, err := q.db.ExecContext(ctx, deleteCustomer, id)
|
||||
return err
|
||||
}
|
||||
|
||||
const updateCustomer = `-- name: UpdateCustomer :one
|
||||
SELECT id, index_id, merchant_id, name, detail, created_at, updated_at FROM customers
|
||||
WHERE id = $1
|
||||
`
|
||||
|
||||
func (q *Queries) UpdateCustomer(ctx context.Context, id uuid.UUID) (Customer, error) {
|
||||
row := q.db.QueryRowContext(ctx, updateCustomer, id)
|
||||
var i Customer
|
||||
err := row.Scan(
|
||||
&i.ID,
|
||||
&i.IndexID,
|
||||
&i.MerchantID,
|
||||
&i.Name,
|
||||
&i.Detail,
|
||||
&i.CreatedAt,
|
||||
&i.UpdatedAt,
|
||||
)
|
||||
return i, err
|
||||
}
|
31
db/sqlc/db.go
Normal file
31
db/sqlc/db.go
Normal file
@ -0,0 +1,31 @@
|
||||
// Code generated by sqlc. DO NOT EDIT.
|
||||
// versions:
|
||||
// sqlc v1.17.2
|
||||
|
||||
package db
|
||||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
)
|
||||
|
||||
type DBTX interface {
|
||||
ExecContext(context.Context, string, ...interface{}) (sql.Result, error)
|
||||
PrepareContext(context.Context, string) (*sql.Stmt, error)
|
||||
QueryContext(context.Context, string, ...interface{}) (*sql.Rows, error)
|
||||
QueryRowContext(context.Context, string, ...interface{}) *sql.Row
|
||||
}
|
||||
|
||||
func New(db DBTX) *Queries {
|
||||
return &Queries{db: db}
|
||||
}
|
||||
|
||||
type Queries struct {
|
||||
db DBTX
|
||||
}
|
||||
|
||||
func (q *Queries) WithTx(tx *sql.Tx) *Queries {
|
||||
return &Queries{
|
||||
db: tx,
|
||||
}
|
||||
}
|
30
db/sqlc/main_test.go
Normal file
30
db/sqlc/main_test.go
Normal file
@ -0,0 +1,30 @@
|
||||
package db
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"log"
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
_ "github.com/lib/pq"
|
||||
)
|
||||
|
||||
const (
|
||||
dbDriver = "postgres"
|
||||
dbSource = "postgresql://postgres:awksed123@localhost:5432/nice_pos?sslmode=disable"
|
||||
)
|
||||
|
||||
var testQueries *Queries
|
||||
var testDB *sql.DB
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
var err error
|
||||
testDB, err = sql.Open(dbDriver, dbSource)
|
||||
if err != nil {
|
||||
log.Fatal("cannot connect to db:", err)
|
||||
}
|
||||
|
||||
testQueries = New(testDB)
|
||||
|
||||
os.Exit(m.Run())
|
||||
}
|
50
db/sqlc/merchant.sql.go
Normal file
50
db/sqlc/merchant.sql.go
Normal file
@ -0,0 +1,50 @@
|
||||
// Code generated by sqlc. DO NOT EDIT.
|
||||
// versions:
|
||||
// sqlc v1.17.2
|
||||
// source: merchant.sql
|
||||
|
||||
package db
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/google/uuid"
|
||||
)
|
||||
|
||||
const getMerchantById = `-- name: GetMerchantById :one
|
||||
SELECT id, index_id, name, owner_id, created_at, updated_at FROM merchants
|
||||
WHERE id = $1
|
||||
`
|
||||
|
||||
func (q *Queries) GetMerchantById(ctx context.Context, id uuid.UUID) (Merchant, error) {
|
||||
row := q.db.QueryRowContext(ctx, getMerchantById, id)
|
||||
var i Merchant
|
||||
err := row.Scan(
|
||||
&i.ID,
|
||||
&i.IndexID,
|
||||
&i.Name,
|
||||
&i.OwnerID,
|
||||
&i.CreatedAt,
|
||||
&i.UpdatedAt,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const getMerchantByUserId = `-- name: GetMerchantByUserId :one
|
||||
SELECT id, index_id, name, owner_id, created_at, updated_at FROM merchants
|
||||
WHERE owner_id = $1
|
||||
`
|
||||
|
||||
func (q *Queries) GetMerchantByUserId(ctx context.Context, ownerID uuid.UUID) (Merchant, error) {
|
||||
row := q.db.QueryRowContext(ctx, getMerchantByUserId, ownerID)
|
||||
var i Merchant
|
||||
err := row.Scan(
|
||||
&i.ID,
|
||||
&i.IndexID,
|
||||
&i.Name,
|
||||
&i.OwnerID,
|
||||
&i.CreatedAt,
|
||||
&i.UpdatedAt,
|
||||
)
|
||||
return i, err
|
||||
}
|
119
db/sqlc/models.go
Normal file
119
db/sqlc/models.go
Normal file
@ -0,0 +1,119 @@
|
||||
// Code generated by sqlc. DO NOT EDIT.
|
||||
// versions:
|
||||
// sqlc v1.17.2
|
||||
|
||||
package db
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
|
||||
"github.com/google/uuid"
|
||||
"github.com/tabbed/pqtype"
|
||||
)
|
||||
|
||||
type Customer struct {
|
||||
ID uuid.UUID `json:"id"`
|
||||
IndexID int64 `json:"index_id"`
|
||||
MerchantID uuid.UUID `json:"merchant_id"`
|
||||
Name string `json:"name"`
|
||||
Detail pqtype.NullRawMessage `json:"detail"`
|
||||
CreatedAt sql.NullTime `json:"created_at"`
|
||||
UpdatedAt sql.NullTime `json:"updated_at"`
|
||||
}
|
||||
|
||||
type Merchant struct {
|
||||
ID uuid.UUID `json:"id"`
|
||||
IndexID int64 `json:"index_id"`
|
||||
Name string `json:"name"`
|
||||
OwnerID uuid.UUID `json:"owner_id"`
|
||||
CreatedAt sql.NullTime `json:"created_at"`
|
||||
UpdatedAt sql.NullTime `json:"updated_at"`
|
||||
}
|
||||
|
||||
type Product struct {
|
||||
ID uuid.UUID `json:"id"`
|
||||
MerchantID uuid.UUID `json:"merchant_id"`
|
||||
IndexID int64 `json:"index_id"`
|
||||
Name string `json:"name"`
|
||||
SellingPrice float64 `json:"selling_price"`
|
||||
PurchasePrice float64 `json:"purchase_price"`
|
||||
Stock float64 `json:"stock"`
|
||||
CreatedAt sql.NullTime `json:"created_at"`
|
||||
UpdatedAt sql.NullTime `json:"updated_at"`
|
||||
}
|
||||
|
||||
type PurchaseOrder struct {
|
||||
ID uuid.UUID `json:"id"`
|
||||
SupplierID uuid.UUID `json:"supplier_id"`
|
||||
MerchantID uuid.UUID `json:"merchant_id"`
|
||||
IndexID int64 `json:"index_id"`
|
||||
Code sql.NullString `json:"code"`
|
||||
IsPaid bool `json:"is_paid"`
|
||||
Total float64 `json:"total"`
|
||||
PaidNominal float64 `json:"paid_nominal"`
|
||||
Note sql.NullString `json:"note"`
|
||||
CreatedAt sql.NullTime `json:"created_at"`
|
||||
UpdatedAt sql.NullTime `json:"updated_at"`
|
||||
}
|
||||
|
||||
type PurchaseOrderDetail struct {
|
||||
ID uuid.UUID `json:"id"`
|
||||
IndexID int64 `json:"index_id"`
|
||||
Code sql.NullString `json:"code"`
|
||||
MerchantID uuid.UUID `json:"merchant_id"`
|
||||
PurchaseOrderID uuid.UUID `json:"purchase_order_id"`
|
||||
ProductID uuid.UUID `json:"product_id"`
|
||||
Quantity float64 `json:"quantity"`
|
||||
SubTotal float64 `json:"sub_total"`
|
||||
ProductPrice float64 `json:"product_price"`
|
||||
CreatedAt sql.NullTime `json:"created_at"`
|
||||
UpdatedAt sql.NullTime `json:"updated_at"`
|
||||
}
|
||||
|
||||
type SaleOrder struct {
|
||||
ID uuid.UUID `json:"id"`
|
||||
IndexID int64 `json:"index_id"`
|
||||
Code sql.NullString `json:"code"`
|
||||
MerchantID uuid.UUID `json:"merchant_id"`
|
||||
CustomerID uuid.NullUUID `json:"customer_id"`
|
||||
IsPaid sql.NullBool `json:"is_paid"`
|
||||
Total float64 `json:"total"`
|
||||
PaidNominal float64 `json:"paid_nominal"`
|
||||
Note sql.NullString `json:"note"`
|
||||
CreatedAt sql.NullTime `json:"created_at"`
|
||||
UpdatedAt sql.NullTime `json:"updated_at"`
|
||||
}
|
||||
|
||||
type SaleOrderDetail struct {
|
||||
ID uuid.UUID `json:"id"`
|
||||
IndexID int64 `json:"index_id"`
|
||||
SaleOrderID uuid.UUID `json:"sale_order_id"`
|
||||
ProductID uuid.UUID `json:"product_id"`
|
||||
ProductName string `json:"product_name"`
|
||||
Quantity float64 `json:"quantity"`
|
||||
SubTotal float64 `json:"sub_total"`
|
||||
ProductPrice float64 `json:"product_price"`
|
||||
Profit float64 `json:"profit"`
|
||||
CreatedAt sql.NullTime `json:"created_at"`
|
||||
UpdatedAt sql.NullTime `json:"updated_at"`
|
||||
}
|
||||
|
||||
type Supplier struct {
|
||||
ID uuid.UUID `json:"id"`
|
||||
IndexID int64 `json:"index_id"`
|
||||
MerchantID uuid.UUID `json:"merchant_id"`
|
||||
Name string `json:"name"`
|
||||
Detail pqtype.NullRawMessage `json:"detail"`
|
||||
CreatedAt sql.NullTime `json:"created_at"`
|
||||
UpdatedAt sql.NullTime `json:"updated_at"`
|
||||
}
|
||||
|
||||
type User struct {
|
||||
ID uuid.UUID `json:"id"`
|
||||
IndexID int64 `json:"index_id"`
|
||||
Email string `json:"email"`
|
||||
Password string `json:"password"`
|
||||
Fullname sql.NullString `json:"fullname"`
|
||||
CreatedAt sql.NullTime `json:"created_at"`
|
||||
UpdatedAt sql.NullTime `json:"updated_at"`
|
||||
}
|
192
db/sqlc/products.sql.go
Normal file
192
db/sqlc/products.sql.go
Normal file
@ -0,0 +1,192 @@
|
||||
// Code generated by sqlc. DO NOT EDIT.
|
||||
// versions:
|
||||
// sqlc v1.17.2
|
||||
// source: products.sql
|
||||
|
||||
package db
|
||||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
|
||||
"github.com/google/uuid"
|
||||
)
|
||||
|
||||
const createProduct = `-- name: CreateProduct :one
|
||||
INSERT INTO products (
|
||||
merchant_id,
|
||||
name,
|
||||
selling_price,
|
||||
purchase_price,
|
||||
stock
|
||||
) VALUES (
|
||||
$1, $2, $3, $4, $5
|
||||
)
|
||||
RETURNING id, merchant_id, index_id, name, selling_price, purchase_price, stock, created_at, updated_at
|
||||
`
|
||||
|
||||
type CreateProductParams struct {
|
||||
MerchantID uuid.UUID `json:"merchant_id"`
|
||||
Name string `json:"name"`
|
||||
SellingPrice float64 `json:"selling_price"`
|
||||
PurchasePrice float64 `json:"purchase_price"`
|
||||
Stock float64 `json:"stock"`
|
||||
}
|
||||
|
||||
func (q *Queries) CreateProduct(ctx context.Context, arg CreateProductParams) (Product, error) {
|
||||
row := q.db.QueryRowContext(ctx, createProduct,
|
||||
arg.MerchantID,
|
||||
arg.Name,
|
||||
arg.SellingPrice,
|
||||
arg.PurchasePrice,
|
||||
arg.Stock,
|
||||
)
|
||||
var i Product
|
||||
err := row.Scan(
|
||||
&i.ID,
|
||||
&i.MerchantID,
|
||||
&i.IndexID,
|
||||
&i.Name,
|
||||
&i.SellingPrice,
|
||||
&i.PurchasePrice,
|
||||
&i.Stock,
|
||||
&i.CreatedAt,
|
||||
&i.UpdatedAt,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const deleteProduct = `-- name: DeleteProduct :exec
|
||||
DELETE FROM products WHERE id = $1
|
||||
`
|
||||
|
||||
func (q *Queries) DeleteProduct(ctx context.Context, id uuid.UUID) error {
|
||||
_, err := q.db.ExecContext(ctx, deleteProduct, id)
|
||||
return err
|
||||
}
|
||||
|
||||
const getProduct = `-- name: GetProduct :one
|
||||
SELECT id, merchant_id, index_id, name, selling_price, purchase_price, stock, created_at, updated_at FROM products
|
||||
WHERE id = $1
|
||||
`
|
||||
|
||||
func (q *Queries) GetProduct(ctx context.Context, id uuid.UUID) (Product, error) {
|
||||
row := q.db.QueryRowContext(ctx, getProduct, id)
|
||||
var i Product
|
||||
err := row.Scan(
|
||||
&i.ID,
|
||||
&i.MerchantID,
|
||||
&i.IndexID,
|
||||
&i.Name,
|
||||
&i.SellingPrice,
|
||||
&i.PurchasePrice,
|
||||
&i.Stock,
|
||||
&i.CreatedAt,
|
||||
&i.UpdatedAt,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const listProducts = `-- name: ListProducts :many
|
||||
SELECT id, merchant_id, index_id, name, selling_price, purchase_price, stock, created_at, updated_at FROM products
|
||||
ORDER BY index_id
|
||||
LIMIT $1
|
||||
OFFSET $2
|
||||
`
|
||||
|
||||
type ListProductsParams struct {
|
||||
Limit int32 `json:"limit"`
|
||||
Offset int32 `json:"offset"`
|
||||
}
|
||||
|
||||
func (q *Queries) ListProducts(ctx context.Context, arg ListProductsParams) ([]Product, error) {
|
||||
rows, err := q.db.QueryContext(ctx, listProducts, arg.Limit, arg.Offset)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
var items []Product
|
||||
for rows.Next() {
|
||||
var i Product
|
||||
if err := rows.Scan(
|
||||
&i.ID,
|
||||
&i.MerchantID,
|
||||
&i.IndexID,
|
||||
&i.Name,
|
||||
&i.SellingPrice,
|
||||
&i.PurchasePrice,
|
||||
&i.Stock,
|
||||
&i.CreatedAt,
|
||||
&i.UpdatedAt,
|
||||
); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
items = append(items, i)
|
||||
}
|
||||
if err := rows.Close(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := rows.Err(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return items, nil
|
||||
}
|
||||
|
||||
const updateProduct = `-- name: UpdateProduct :one
|
||||
UPDATE products
|
||||
SET name = $2, selling_price = $3, purchase_price = $4, stock = $5, updated_at = $6
|
||||
WHERE id = $1
|
||||
RETURNING id, merchant_id, index_id, name, selling_price, purchase_price, stock, created_at, updated_at
|
||||
`
|
||||
|
||||
type UpdateProductParams struct {
|
||||
ID uuid.UUID `json:"id"`
|
||||
Name string `json:"name"`
|
||||
SellingPrice float64 `json:"selling_price"`
|
||||
PurchasePrice float64 `json:"purchase_price"`
|
||||
Stock float64 `json:"stock"`
|
||||
UpdatedAt sql.NullTime `json:"updated_at"`
|
||||
}
|
||||
|
||||
func (q *Queries) UpdateProduct(ctx context.Context, arg UpdateProductParams) (Product, error) {
|
||||
row := q.db.QueryRowContext(ctx, updateProduct,
|
||||
arg.ID,
|
||||
arg.Name,
|
||||
arg.SellingPrice,
|
||||
arg.PurchasePrice,
|
||||
arg.Stock,
|
||||
arg.UpdatedAt,
|
||||
)
|
||||
var i Product
|
||||
err := row.Scan(
|
||||
&i.ID,
|
||||
&i.MerchantID,
|
||||
&i.IndexID,
|
||||
&i.Name,
|
||||
&i.SellingPrice,
|
||||
&i.PurchasePrice,
|
||||
&i.Stock,
|
||||
&i.CreatedAt,
|
||||
&i.UpdatedAt,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const updateProductStock = `-- name: UpdateProductStock :one
|
||||
UPDATE products
|
||||
SET stock = $1
|
||||
WHERE id = $2
|
||||
RETURNING stock
|
||||
`
|
||||
|
||||
type UpdateProductStockParams struct {
|
||||
Stock float64 `json:"stock"`
|
||||
ID uuid.UUID `json:"id"`
|
||||
}
|
||||
|
||||
func (q *Queries) UpdateProductStock(ctx context.Context, arg UpdateProductStockParams) (float64, error) {
|
||||
row := q.db.QueryRowContext(ctx, updateProductStock, arg.Stock, arg.ID)
|
||||
var stock float64
|
||||
err := row.Scan(&stock)
|
||||
return stock, err
|
||||
}
|
124
db/sqlc/products_test.go
Normal file
124
db/sqlc/products_test.go
Normal file
@ -0,0 +1,124 @@
|
||||
package db
|
||||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"git.nochill.in/nochill/nice_pos/util"
|
||||
"github.com/google/uuid"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func createRandomProduct(t *testing.T) (Product, CreateProductParams) {
|
||||
|
||||
arg := CreateProductParams{
|
||||
MerchantID: uuid.MustParse("1f81d072-0c98-4e7e-9ceb-233d2eadb674"),
|
||||
Name: util.RandomString(10),
|
||||
SellingPrice: float64(123),
|
||||
PurchasePrice: float64(123),
|
||||
Stock: float64(120),
|
||||
}
|
||||
|
||||
product, err := testQueries.CreateProduct(context.Background(), arg)
|
||||
require.NoError(t, err)
|
||||
|
||||
return product, arg
|
||||
|
||||
}
|
||||
|
||||
func TestCreateProduct(t *testing.T) {
|
||||
product, arg := createRandomProduct(t)
|
||||
require.NotEmpty(t, product)
|
||||
|
||||
require.Equal(t, arg.Name, product.Name)
|
||||
require.Equal(t, arg.MerchantID, product.MerchantID)
|
||||
require.Equal(t, arg.SellingPrice, product.SellingPrice)
|
||||
require.Equal(t, arg.PurchasePrice, product.PurchasePrice)
|
||||
require.Equal(t, arg.Stock, product.Stock)
|
||||
|
||||
require.NotZero(t, product.ID)
|
||||
require.NotZero(t, product.CreatedAt)
|
||||
require.NotZero(t, product.UpdatedAt)
|
||||
}
|
||||
|
||||
func TestGetProduct(t *testing.T) {
|
||||
createProduct, _ := createRandomProduct(t)
|
||||
getProduct, err := testQueries.GetProduct(context.Background(), createProduct.ID)
|
||||
|
||||
require.NoError(t, err)
|
||||
require.NotEmpty(t, getProduct)
|
||||
|
||||
require.Equal(t, createProduct.ID, getProduct.ID)
|
||||
require.Equal(t, createProduct.MerchantID, getProduct.MerchantID)
|
||||
require.Equal(t, createProduct.Name, getProduct.Name)
|
||||
require.Equal(t, createProduct.PurchasePrice, getProduct.PurchasePrice)
|
||||
require.Equal(t, createProduct.SellingPrice, getProduct.SellingPrice)
|
||||
require.Equal(t, createProduct.Stock, getProduct.Stock)
|
||||
|
||||
require.WithinDuration(t, createProduct.CreatedAt.Time, getProduct.CreatedAt.Time, time.Second)
|
||||
require.WithinDuration(t, createProduct.UpdatedAt.Time, getProduct.UpdatedAt.Time, time.Second)
|
||||
}
|
||||
|
||||
func TestUpdateProduct(t *testing.T) {
|
||||
createProduct, _ := createRandomProduct(t)
|
||||
getProduct, err := testQueries.GetProduct(context.Background(), createProduct.ID)
|
||||
|
||||
require.NoError(t, err)
|
||||
|
||||
arg := UpdateProductParams{
|
||||
ID: getProduct.ID,
|
||||
Name: util.RandomString(6),
|
||||
SellingPrice: float64(200),
|
||||
PurchasePrice: float64(200),
|
||||
Stock: float64(200),
|
||||
}
|
||||
|
||||
updatedProduct, err := testQueries.UpdateProduct(context.Background(), arg)
|
||||
|
||||
require.NotEmpty(t, updatedProduct)
|
||||
require.NoError(t, err)
|
||||
|
||||
require.Equal(t, arg.ID, updatedProduct.ID)
|
||||
require.Equal(t, arg.Name, updatedProduct.Name)
|
||||
require.Equal(t, arg.PurchasePrice, updatedProduct.PurchasePrice)
|
||||
require.Equal(t, arg.SellingPrice, updatedProduct.SellingPrice)
|
||||
require.Equal(t, arg.Stock, updatedProduct.Stock)
|
||||
|
||||
require.NotSame(t, createProduct.Name, updatedProduct.Name)
|
||||
require.NotSame(t, createProduct.SellingPrice, updatedProduct.SellingPrice)
|
||||
require.NotSame(t, createProduct.PurchasePrice, updatedProduct.PurchasePrice)
|
||||
require.NotSame(t, createProduct.Stock, updatedProduct.Stock)
|
||||
}
|
||||
|
||||
func TestDeleteProduct(t *testing.T) {
|
||||
product1, _ := createRandomProduct(t)
|
||||
err := testQueries.DeleteProduct(context.Background(), product1.ID)
|
||||
require.NoError(t, err)
|
||||
|
||||
product2, err := testQueries.GetProduct(context.Background(), product1.ID)
|
||||
require.Error(t, err)
|
||||
require.EqualError(t, err, sql.ErrNoRows.Error())
|
||||
require.Empty(t, product2)
|
||||
}
|
||||
|
||||
func TestGetProducts(t *testing.T) {
|
||||
for i := 0; i < 6; i++ {
|
||||
createRandomProduct(t)
|
||||
}
|
||||
|
||||
arg := ListProductsParams{
|
||||
Limit: 5,
|
||||
Offset: 5,
|
||||
}
|
||||
|
||||
products, err := testQueries.ListProducts(context.Background(), arg)
|
||||
require.NoError(t, err)
|
||||
require.Len(t, products, 5)
|
||||
|
||||
for _, product := range products {
|
||||
require.NotEmpty(t, product)
|
||||
}
|
||||
|
||||
}
|
65
db/sqlc/purchase_order.sql.go
Normal file
65
db/sqlc/purchase_order.sql.go
Normal file
@ -0,0 +1,65 @@
|
||||
// Code generated by sqlc. DO NOT EDIT.
|
||||
// versions:
|
||||
// sqlc v1.17.2
|
||||
// source: purchase_order.sql
|
||||
|
||||
package db
|
||||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
|
||||
"github.com/google/uuid"
|
||||
)
|
||||
|
||||
const createPurchaseOrder = `-- name: CreatePurchaseOrder :one
|
||||
INSERT INTO purchase_order (
|
||||
merchant_id,
|
||||
supplier_id,
|
||||
code,
|
||||
is_paid,
|
||||
total,
|
||||
paid_nominal,
|
||||
note
|
||||
) VALUES (
|
||||
$1, $2, $3, $4, $5, $6, $7
|
||||
)
|
||||
RETURNING id, supplier_id, merchant_id, index_id, code, is_paid, total, paid_nominal, note, created_at, updated_at
|
||||
`
|
||||
|
||||
type CreatePurchaseOrderParams struct {
|
||||
MerchantID uuid.UUID `json:"merchant_id"`
|
||||
SupplierID uuid.UUID `json:"supplier_id"`
|
||||
Code sql.NullString `json:"code"`
|
||||
IsPaid bool `json:"is_paid"`
|
||||
Total float64 `json:"total"`
|
||||
PaidNominal float64 `json:"paid_nominal"`
|
||||
Note sql.NullString `json:"note"`
|
||||
}
|
||||
|
||||
func (q *Queries) CreatePurchaseOrder(ctx context.Context, arg CreatePurchaseOrderParams) (PurchaseOrder, error) {
|
||||
row := q.db.QueryRowContext(ctx, createPurchaseOrder,
|
||||
arg.MerchantID,
|
||||
arg.SupplierID,
|
||||
arg.Code,
|
||||
arg.IsPaid,
|
||||
arg.Total,
|
||||
arg.PaidNominal,
|
||||
arg.Note,
|
||||
)
|
||||
var i PurchaseOrder
|
||||
err := row.Scan(
|
||||
&i.ID,
|
||||
&i.SupplierID,
|
||||
&i.MerchantID,
|
||||
&i.IndexID,
|
||||
&i.Code,
|
||||
&i.IsPaid,
|
||||
&i.Total,
|
||||
&i.PaidNominal,
|
||||
&i.Note,
|
||||
&i.CreatedAt,
|
||||
&i.UpdatedAt,
|
||||
)
|
||||
return i, err
|
||||
}
|
61
db/sqlc/purchase_order_detail.sql.go
Normal file
61
db/sqlc/purchase_order_detail.sql.go
Normal file
@ -0,0 +1,61 @@
|
||||
// Code generated by sqlc. DO NOT EDIT.
|
||||
// versions:
|
||||
// sqlc v1.17.2
|
||||
// source: purchase_order_detail.sql
|
||||
|
||||
package db
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/google/uuid"
|
||||
)
|
||||
|
||||
const createPurchaseOrderDetail = `-- name: CreatePurchaseOrderDetail :one
|
||||
INSERT INTO purchase_order_detail (
|
||||
purchase_order_id,
|
||||
merchant_id,
|
||||
product_id,
|
||||
quantity,
|
||||
sub_total,
|
||||
product_price
|
||||
) VALUES (
|
||||
$1, $2, $3, $4, $5, $6
|
||||
)
|
||||
RETURNING id, index_id, code, merchant_id, purchase_order_id, product_id, quantity, sub_total, product_price, created_at, updated_at
|
||||
`
|
||||
|
||||
type CreatePurchaseOrderDetailParams struct {
|
||||
PurchaseOrderID uuid.UUID `json:"purchase_order_id"`
|
||||
MerchantID uuid.UUID `json:"merchant_id"`
|
||||
ProductID uuid.UUID `json:"product_id"`
|
||||
Quantity float64 `json:"quantity"`
|
||||
SubTotal float64 `json:"sub_total"`
|
||||
ProductPrice float64 `json:"product_price"`
|
||||
}
|
||||
|
||||
func (q *Queries) CreatePurchaseOrderDetail(ctx context.Context, arg CreatePurchaseOrderDetailParams) (PurchaseOrderDetail, error) {
|
||||
row := q.db.QueryRowContext(ctx, createPurchaseOrderDetail,
|
||||
arg.PurchaseOrderID,
|
||||
arg.MerchantID,
|
||||
arg.ProductID,
|
||||
arg.Quantity,
|
||||
arg.SubTotal,
|
||||
arg.ProductPrice,
|
||||
)
|
||||
var i PurchaseOrderDetail
|
||||
err := row.Scan(
|
||||
&i.ID,
|
||||
&i.IndexID,
|
||||
&i.Code,
|
||||
&i.MerchantID,
|
||||
&i.PurchaseOrderID,
|
||||
&i.ProductID,
|
||||
&i.Quantity,
|
||||
&i.SubTotal,
|
||||
&i.ProductPrice,
|
||||
&i.CreatedAt,
|
||||
&i.UpdatedAt,
|
||||
)
|
||||
return i, err
|
||||
}
|
88
db/sqlc/store.go
Normal file
88
db/sqlc/store.go
Normal file
@ -0,0 +1,88 @@
|
||||
package db
|
||||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"fmt"
|
||||
|
||||
"github.com/google/uuid"
|
||||
)
|
||||
|
||||
type Store struct {
|
||||
*Queries
|
||||
db *sql.DB
|
||||
}
|
||||
|
||||
func NewStore(db *sql.DB) *Store {
|
||||
return &Store{
|
||||
db: db,
|
||||
Queries: New(db),
|
||||
}
|
||||
}
|
||||
|
||||
func (store *Store) execTx(ctx context.Context, fn func(*Queries) error) error {
|
||||
tx, err := store.db.BeginTx(ctx, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
q := New(tx)
|
||||
err = fn(q)
|
||||
if err != nil {
|
||||
if rbErr := tx.Rollback(); rbErr != nil {
|
||||
return fmt.Errorf("tx err: %v, rb err : %v", err, rbErr)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
return tx.Commit()
|
||||
|
||||
}
|
||||
|
||||
type PurchaseOrderProduct struct {
|
||||
ProductID uuid.UUID `json:"product_id"`
|
||||
Quantity float64 `json:"quantity"`
|
||||
Sub_total float64 `json:"sub_total"`
|
||||
Price float64 `json:"price"`
|
||||
}
|
||||
|
||||
type PurchasoOrderTxParams struct {
|
||||
MerchantID uuid.UUID `json:"merchant_id"`
|
||||
SupplierID uuid.UUID `json:"supplier_id"`
|
||||
Code sql.NullString `json:"code"`
|
||||
IsPaid bool `json:"is_paid"`
|
||||
Total float64 `json:"total"`
|
||||
PaidNominal float64 `json:"paid_nominal"`
|
||||
Note sql.NullString `json:"note"`
|
||||
Products []PurchaseOrderProduct `json:"products"`
|
||||
}
|
||||
|
||||
type PurchaseOrderTxResult struct {
|
||||
PurchaseOrder PurchaseOrder `json:"purchase_order"`
|
||||
// PurchaseOrderDetail []PurchaseOrderDetail `json:"detail"`
|
||||
}
|
||||
|
||||
func (store *Store) PurchaseOrderTx(ctx context.Context, arg PurchasoOrderTxParams) (PurchaseOrderTxResult, error) {
|
||||
var result PurchaseOrderTxResult
|
||||
|
||||
err := store.execTx(ctx, func(q *Queries) error {
|
||||
var err error
|
||||
result.PurchaseOrder, err = q.CreatePurchaseOrder(ctx, CreatePurchaseOrderParams{
|
||||
MerchantID: arg.MerchantID,
|
||||
SupplierID: arg.SupplierID,
|
||||
Code: arg.Code,
|
||||
IsPaid: arg.IsPaid,
|
||||
Total: arg.Total,
|
||||
PaidNominal: arg.PaidNominal,
|
||||
Note: arg.Note,
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
|
||||
return result, err
|
||||
}
|
45
db/sqlc/store_test.go
Normal file
45
db/sqlc/store_test.go
Normal file
@ -0,0 +1,45 @@
|
||||
package db
|
||||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestPurchaseOrder(t *testing.T) {
|
||||
store := NewStore(testDB)
|
||||
supplier, _ := createRandomSupplier(t)
|
||||
product1, _ := createRandomProduct(t)
|
||||
product2, _ := createRandomProduct(t)
|
||||
|
||||
errs := make(chan error)
|
||||
results := make(chan PurchaseOrderTxResult)
|
||||
|
||||
// for i := 0; i < testIteration; i++ {
|
||||
go func() {
|
||||
result, err := store.PurchaseOrderTx(context.Background(), PurchasoOrderTxParams{
|
||||
MerchantID: supplier.MerchantID,
|
||||
SupplierID: supplier.ID,
|
||||
Code: sql.NullString{Valid: true, String: ""},
|
||||
IsPaid: true,
|
||||
Total: product1.PurchasePrice + product2.PurchasePrice,
|
||||
PaidNominal: product1.PurchasePrice + product2.PurchasePrice,
|
||||
Note: sql.NullString{Valid: true, String: ""},
|
||||
// Products: products,
|
||||
|
||||
})
|
||||
errs <- err
|
||||
results <- result
|
||||
}()
|
||||
// }
|
||||
|
||||
// for i := 0; i < testIteration; i++ {
|
||||
err := <-errs
|
||||
require.NoError(t, err)
|
||||
|
||||
result := <-results
|
||||
require.NotEmpty(t, result)
|
||||
|
||||
}
|
119
db/sqlc/suppliers.sql.go
Normal file
119
db/sqlc/suppliers.sql.go
Normal file
@ -0,0 +1,119 @@
|
||||
// Code generated by sqlc. DO NOT EDIT.
|
||||
// versions:
|
||||
// sqlc v1.17.2
|
||||
// source: suppliers.sql
|
||||
|
||||
package db
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/google/uuid"
|
||||
"github.com/tabbed/pqtype"
|
||||
)
|
||||
|
||||
const createSuppliers = `-- name: CreateSuppliers :one
|
||||
INSERT INTO suppliers (
|
||||
merchant_id,
|
||||
name,
|
||||
detail
|
||||
) VALUES (
|
||||
$1, $2, $3
|
||||
)
|
||||
RETURNING id, index_id, merchant_id, name, detail, created_at, updated_at
|
||||
`
|
||||
|
||||
type CreateSuppliersParams struct {
|
||||
MerchantID uuid.UUID `json:"merchant_id"`
|
||||
Name string `json:"name"`
|
||||
Detail pqtype.NullRawMessage `json:"detail"`
|
||||
}
|
||||
|
||||
func (q *Queries) CreateSuppliers(ctx context.Context, arg CreateSuppliersParams) (Supplier, error) {
|
||||
row := q.db.QueryRowContext(ctx, createSuppliers, arg.MerchantID, arg.Name, arg.Detail)
|
||||
var i Supplier
|
||||
err := row.Scan(
|
||||
&i.ID,
|
||||
&i.IndexID,
|
||||
&i.MerchantID,
|
||||
&i.Name,
|
||||
&i.Detail,
|
||||
&i.CreatedAt,
|
||||
&i.UpdatedAt,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const deleteSupplier = `-- name: DeleteSupplier :exec
|
||||
DELETE FROM suppliers where id = $1
|
||||
`
|
||||
|
||||
func (q *Queries) DeleteSupplier(ctx context.Context, id uuid.UUID) error {
|
||||
_, err := q.db.ExecContext(ctx, deleteSupplier, id)
|
||||
return err
|
||||
}
|
||||
|
||||
const suppliersList = `-- name: SuppliersList :many
|
||||
SELECT id, index_id, merchant_id, name, detail, created_at, updated_at FROM suppliers
|
||||
WHERE merchant_id = $1
|
||||
ORDER BY index_id
|
||||
LIMIT $2
|
||||
OFFSET $3
|
||||
`
|
||||
|
||||
type SuppliersListParams struct {
|
||||
MerchantID uuid.UUID `json:"merchant_id"`
|
||||
Limit int32 `json:"limit"`
|
||||
Offset int32 `json:"offset"`
|
||||
}
|
||||
|
||||
func (q *Queries) SuppliersList(ctx context.Context, arg SuppliersListParams) ([]Supplier, error) {
|
||||
rows, err := q.db.QueryContext(ctx, suppliersList, arg.MerchantID, arg.Limit, arg.Offset)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
var items []Supplier
|
||||
for rows.Next() {
|
||||
var i Supplier
|
||||
if err := rows.Scan(
|
||||
&i.ID,
|
||||
&i.IndexID,
|
||||
&i.MerchantID,
|
||||
&i.Name,
|
||||
&i.Detail,
|
||||
&i.CreatedAt,
|
||||
&i.UpdatedAt,
|
||||
); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
items = append(items, i)
|
||||
}
|
||||
if err := rows.Close(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := rows.Err(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return items, nil
|
||||
}
|
||||
|
||||
const updateSupplier = `-- name: UpdateSupplier :one
|
||||
SELECT id, index_id, merchant_id, name, detail, created_at, updated_at FROM suppliers
|
||||
WHERE id = $1
|
||||
`
|
||||
|
||||
func (q *Queries) UpdateSupplier(ctx context.Context, id uuid.UUID) (Supplier, error) {
|
||||
row := q.db.QueryRowContext(ctx, updateSupplier, id)
|
||||
var i Supplier
|
||||
err := row.Scan(
|
||||
&i.ID,
|
||||
&i.IndexID,
|
||||
&i.MerchantID,
|
||||
&i.Name,
|
||||
&i.Detail,
|
||||
&i.CreatedAt,
|
||||
&i.UpdatedAt,
|
||||
)
|
||||
return i, err
|
||||
}
|
36
db/sqlc/suppliers_test.go
Normal file
36
db/sqlc/suppliers_test.go
Normal file
@ -0,0 +1,36 @@
|
||||
package db
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"git.nochill.in/nochill/nice_pos/util"
|
||||
"github.com/google/uuid"
|
||||
"github.com/stretchr/testify/require"
|
||||
"github.com/tabbed/pqtype"
|
||||
)
|
||||
|
||||
func createRandomSupplier(t *testing.T) (Supplier, CreateSuppliersParams) {
|
||||
arg := CreateSuppliersParams{
|
||||
MerchantID: uuid.MustParse("1f81d072-0c98-4e7e-9ceb-233d2eadb674"),
|
||||
Name: util.RandomString(10),
|
||||
Detail: pqtype.NullRawMessage{},
|
||||
}
|
||||
|
||||
supplier, err := testQueries.CreateSuppliers(context.Background(), arg)
|
||||
require.NoError(t, err)
|
||||
|
||||
return supplier, arg
|
||||
|
||||
}
|
||||
func TestCreateSupplier(t *testing.T) {
|
||||
supplier, arg := createRandomSupplier(t)
|
||||
|
||||
require.Equal(t, arg.Name, supplier.Name)
|
||||
require.Equal(t, arg.MerchantID, supplier.MerchantID)
|
||||
|
||||
require.NotZero(t, supplier.ID)
|
||||
require.NotZero(t, supplier.CreatedAt)
|
||||
require.NotZero(t, supplier.UpdatedAt)
|
||||
|
||||
}
|
16
go.mod
Normal file
16
go.mod
Normal file
@ -0,0 +1,16 @@
|
||||
module git.nochill.in/nochill/nice_pos
|
||||
|
||||
go 1.20
|
||||
|
||||
require (
|
||||
github.com/google/uuid v1.3.0
|
||||
github.com/lib/pq v1.10.7
|
||||
github.com/stretchr/testify v1.8.2
|
||||
github.com/tabbed/pqtype v0.1.1
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
)
|
23
go.sum
Normal file
23
go.sum
Normal file
@ -0,0 +1,23 @@
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
|
||||
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/lib/pq v1.10.7 h1:p7ZhMD+KsSRozJr34udlUrhboJwWAgCg34+/ZZNvZZw=
|
||||
github.com/lib/pq v1.10.7/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
||||
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
|
||||
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
||||
github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8=
|
||||
github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
||||
github.com/tabbed/pqtype v0.1.1 h1:PhEcb9JZ8jr7SUjJDFjRPxny0M8fkXZrxn/a9yQfoZg=
|
||||
github.com/tabbed/pqtype v0.1.1/go.mod h1:HLt2kLJPcUhODQkYn3mJkMHXVsuv3Z2n5NZEeKXL0Uk=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
11
sqlc.yaml
Normal file
11
sqlc.yaml
Normal file
@ -0,0 +1,11 @@
|
||||
version: "1"
|
||||
packages:
|
||||
- name: "db"
|
||||
path: "./db/sqlc"
|
||||
queries: "./db/query/"
|
||||
schema: "./db/migrations/"
|
||||
engine: "postgresql"
|
||||
emit_json_tags: true
|
||||
emit_prepared_queries: false
|
||||
emit_interface: false
|
||||
emit_exact_table_names: false
|
35
util/random.go
Normal file
35
util/random.go
Normal file
@ -0,0 +1,35 @@
|
||||
package util
|
||||
|
||||
import (
|
||||
"math/rand"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
const alphabet = "abcdefghijklmnopqrstuvwxyz"
|
||||
|
||||
func init() {
|
||||
rand.Seed(time.Now().UnixNano())
|
||||
}
|
||||
|
||||
// RandomInt generates a random integer between min and max
|
||||
func RandomInt(min, max int64) int64 {
|
||||
return min + rand.Int63n(max-min+1)
|
||||
}
|
||||
|
||||
func RandomFloat(max, div float64) float64 {
|
||||
return (rand.Float64() * max) * div
|
||||
}
|
||||
|
||||
// RandomString generates a random string of length n
|
||||
func RandomString(n int) string {
|
||||
var sb strings.Builder
|
||||
k := len(alphabet)
|
||||
|
||||
for i := 0; i < n; i++ {
|
||||
c := alphabet[rand.Intn(k)]
|
||||
sb.WriteByte(c)
|
||||
}
|
||||
|
||||
return sb.String()
|
||||
}
|
Loading…
Reference in New Issue
Block a user