feat: add invoice and alternative_componen management functionality

This commit is contained in:
Tran Anh Tuan
2026-05-12 11:57:11 +07:00
parent c39b010e5e
commit e81a248a61
23 changed files with 3325 additions and 2 deletions

View File

@@ -22,6 +22,8 @@ const (
API_GROUP_COMPONENT_ITEM = "/component-items" API_GROUP_COMPONENT_ITEM = "/component-items"
API_GROUP_INVOICE_CONFIG = "/invoice-configs" API_GROUP_INVOICE_CONFIG = "/invoice-configs"
API_GROUP_INVOICE_CONFIG_ITEM = "/invoice-config-items" API_GROUP_INVOICE_CONFIG_ITEM = "/invoice-config-items"
API_GROUP_INVOICE = "/invoices"
API_GROUP_ALTERNATIVE_COMPONENT = "/alternative-components"
) )
const ( const (

View File

@@ -0,0 +1,35 @@
-- name: GetAlternativeComponentByID :one
SELECT * FROM alternative_components
WHERE id = sqlc.arg(id);
-- name: ListAlternativeComponents :many
SELECT * FROM alternative_components;
-- name: CreateAlternativeComponent :one
INSERT INTO alternative_components (invoice_config_item_id, alternative_component_id, conversion_ratio, priority, note, metadata)
VALUES (
sqlc.arg(invoice_config_item_id),
sqlc.arg(alternative_component_id),
sqlc.arg(conversion_ratio),
sqlc.arg(priority),
sqlc.arg(note),
sqlc.arg(metadata)
)
RETURNING *;
-- name: UpdateAlternativeComponent :one
UPDATE alternative_components
SET invoice_config_item_id = coalesce(sqlc.arg(invoice_config_item_id), invoice_config_item_id),
alternative_component_id = coalesce(sqlc.arg(alternative_component_id), alternative_component_id),
conversion_ratio = coalesce(sqlc.arg(conversion_ratio), conversion_ratio),
priority = coalesce(sqlc.arg(priority), priority),
note = coalesce(sqlc.arg(note), note),
metadata = coalesce(sqlc.arg(metadata), metadata)
WHERE id = sqlc.arg(id)
RETURNING *;
-- name: DeleteAlternativeComponent :execrows
DELETE FROM alternative_components
WHERE id = sqlc.arg(id);

40
db/queries/invoice.sql Normal file
View File

@@ -0,0 +1,40 @@
-- name: GetInvoiceByID :one
SELECT * FROM invoices
WHERE id = sqlc.arg(id);
-- name: ListInvoices :many
SELECT * FROM invoices
ORDER BY created_at DESC;
-- name: CreateInvoice :one
INSERT INTO invoices (type, status, invoice_config_id, total_items, note, created_by, approved_by, created_at, metadata)
VALUES (
sqlc.arg(type),
sqlc.arg(status),
sqlc.arg(invoice_config_id),
sqlc.arg(total_items),
sqlc.arg(note),
sqlc.arg(created_by),
sqlc.arg(approved_by),
sqlc.arg(created_at),
sqlc.arg(metadata)
)
RETURNING *;
-- name: UpdateInvoice :one
UPDATE invoices
SET type = coalesce(sqlc.arg(type), type),
status = coalesce(sqlc.arg(status), status),
invoice_config_id = coalesce(sqlc.arg(invoice_config_id), invoice_config_id),
total_items = coalesce(sqlc.arg(total_items), total_items),
note = coalesce(sqlc.arg(note), note),
metadata = coalesce(sqlc.arg(metadata), metadata),
updated_at = sqlc.arg(updated_at)
WHERE id = sqlc.arg(id)
RETURNING *;
-- name: DeleteInvoice :execrows
DELETE FROM invoices
WHERE id = sqlc.arg(id);

View File

@@ -0,0 +1,38 @@
-- name: GetInvoiceItemByID :one
SELECT * FROM invoice_items
WHERE id = sqlc.arg(id);
-- name: ListInvoiceItems :many
SELECT * FROM invoice_items;
-- name: CreateInvoiceItem :one
INSERT INTO invoice_items (invoice_id,component_id,original_component_id, required_quantity,actual_quantity, is_substituted, is_short, shortage_quantity, note, metadata)
VALUES (
sqlc.arg(invoice_id),
sqlc.arg(component_id),
sqlc.arg(original_component_id),
sqlc.arg(required_quantity),
sqlc.arg(actual_quantity),
sqlc.arg(is_substituted),
sqlc.arg(is_short),
sqlc.arg(shortage_quantity),
sqlc.arg(note),
sqlc.arg(metadata)
)
RETURNING *;
-- name: UpdateInvoiceItem :one
UPDATE invoice_items
SET required_quantity = coalesce(sqlc.arg(required_quantity), required_quantity),
actual_quantity = coalesce(sqlc.arg(actual_quantity), actual_quantity),
is_substituted = coalesce(sqlc.arg(is_substituted), is_substituted),
is_short = coalesce(sqlc.arg(is_short), is_short),
shortage_quantity = coalesce(sqlc.arg(shortage_quantity), shortage_quantity),
note = coalesce(sqlc.arg(note), note),
metadata = coalesce(sqlc.arg(metadata), metadata)
WHERE id = sqlc.arg(id)
RETURNING *;
-- name: DeleteInvoiceItem :execrows
DELETE FROM invoice_items
WHERE id = sqlc.arg(id);

View File

@@ -1327,6 +1327,279 @@ const docTemplate = `{
} }
} }
}, },
"/v1/alternative-components": {
"get": {
"description": "Retrieve a list of all alternative components",
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"tags": [
"alternative-component"
],
"summary": "List all alternative components",
"responses": {
"200": {
"description": "OK",
"schema": {
"allOf": [
{
"$ref": "#/definitions/response.SuccessResponse"
},
{
"type": "object",
"properties": {
"data": {
"type": "array",
"items": {
"$ref": "#/definitions/models.AlternativeComponent"
}
}
}
}
]
}
},
"500": {
"description": "Internal Server Error",
"schema": {
"$ref": "#/definitions/response.ErrorResponse"
}
}
}
},
"post": {
"description": "Create a new alternative component with the provided details",
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"tags": [
"alternative-component"
],
"summary": "Create a new alternative component",
"parameters": [
{
"description": "Alternative component request body",
"name": "body",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/requests.CreateAlternativeComponentRequest"
}
}
],
"responses": {
"201": {
"description": "Created",
"schema": {
"allOf": [
{
"$ref": "#/definitions/response.SuccessResponse"
},
{
"type": "object",
"properties": {
"data": {
"$ref": "#/definitions/responses.CreateAlternativeComponentResponse"
}
}
}
]
}
},
"400": {
"description": "Bad Request",
"schema": {
"$ref": "#/definitions/response.ErrorResponse"
}
},
"500": {
"description": "Internal Server Error",
"schema": {
"$ref": "#/definitions/response.ErrorResponse"
}
}
}
}
},
"/v1/alternative-components/{id}": {
"get": {
"description": "Retrieve a single alternative component using its unique identifier",
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"tags": [
"alternative-component"
],
"summary": "Get alternative component by ID",
"parameters": [
{
"type": "integer",
"description": "Alternative component ID",
"name": "id",
"in": "path",
"required": true
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"allOf": [
{
"$ref": "#/definitions/response.SuccessResponse"
},
{
"type": "object",
"properties": {
"data": {
"$ref": "#/definitions/models.AlternativeComponent"
}
}
}
]
}
},
"400": {
"description": "Bad Request",
"schema": {
"$ref": "#/definitions/response.ErrorResponse"
}
},
"404": {
"description": "Not Found",
"schema": {
"$ref": "#/definitions/response.ErrorResponse"
}
},
"500": {
"description": "Internal Server Error",
"schema": {
"$ref": "#/definitions/response.ErrorResponse"
}
}
}
},
"put": {
"description": "Update an existing alternative component by its ID. Only non-empty fields will be updated.",
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"tags": [
"alternative-component"
],
"summary": "Update alternative component",
"parameters": [
{
"type": "integer",
"description": "Alternative component ID",
"name": "id",
"in": "path",
"required": true
},
{
"description": "Alternative component request body",
"name": "body",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/requests.UpdateAlternativeComponentRequest"
}
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"allOf": [
{
"$ref": "#/definitions/response.SuccessResponse"
},
{
"type": "object",
"properties": {
"data": {
"$ref": "#/definitions/responses.UpdateAlternativeComponentResponse"
}
}
}
]
}
},
"400": {
"description": "Bad Request",
"schema": {
"$ref": "#/definitions/response.ErrorResponse"
}
},
"404": {
"description": "Not Found",
"schema": {
"$ref": "#/definitions/response.ErrorResponse"
}
},
"500": {
"description": "Internal Server Error",
"schema": {
"$ref": "#/definitions/response.ErrorResponse"
}
}
}
},
"delete": {
"description": "Delete an alternative component by its unique identifier",
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"tags": [
"alternative-component"
],
"summary": "Delete alternative component",
"parameters": [
{
"type": "integer",
"description": "Alternative component ID",
"name": "id",
"in": "path",
"required": true
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/response.SuccessResponse"
}
},
"400": {
"description": "Bad Request",
"schema": {
"$ref": "#/definitions/response.ErrorResponse"
}
},
"500": {
"description": "Internal Server Error",
"schema": {
"$ref": "#/definitions/response.ErrorResponse"
}
}
}
}
},
"/v1/cabinets": { "/v1/cabinets": {
"get": { "get": {
"description": "Retrieve a list of all cabinets ordered by creation date", "description": "Retrieve a list of all cabinets ordered by creation date",
@@ -2419,6 +2692,279 @@ const docTemplate = `{
} }
} }
}, },
"/v1/invoices": {
"get": {
"description": "Retrieve a list of all invoices ordered by creation date",
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"tags": [
"invoice"
],
"summary": "List all invoices",
"responses": {
"200": {
"description": "OK",
"schema": {
"allOf": [
{
"$ref": "#/definitions/response.SuccessResponse"
},
{
"type": "object",
"properties": {
"data": {
"type": "array",
"items": {
"$ref": "#/definitions/models.Invoice"
}
}
}
}
]
}
},
"500": {
"description": "Internal Server Error",
"schema": {
"$ref": "#/definitions/response.ErrorResponse"
}
}
}
},
"post": {
"description": "Create a new invoice with the provided details",
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"tags": [
"invoice"
],
"summary": "Create a new invoice",
"parameters": [
{
"description": "Invoice request body",
"name": "body",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/requests.CreateInvoiceRequest"
}
}
],
"responses": {
"201": {
"description": "Created",
"schema": {
"allOf": [
{
"$ref": "#/definitions/response.SuccessResponse"
},
{
"type": "object",
"properties": {
"data": {
"$ref": "#/definitions/responses.CreateInvoiceResponse"
}
}
}
]
}
},
"400": {
"description": "Bad Request",
"schema": {
"$ref": "#/definitions/response.ErrorResponse"
}
},
"500": {
"description": "Internal Server Error",
"schema": {
"$ref": "#/definitions/response.ErrorResponse"
}
}
}
}
},
"/v1/invoices/{id}": {
"get": {
"description": "Retrieve a single invoice using its unique identifier",
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"tags": [
"invoice"
],
"summary": "Get invoice by ID",
"parameters": [
{
"type": "integer",
"description": "Invoice ID",
"name": "id",
"in": "path",
"required": true
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"allOf": [
{
"$ref": "#/definitions/response.SuccessResponse"
},
{
"type": "object",
"properties": {
"data": {
"$ref": "#/definitions/models.Invoice"
}
}
}
]
}
},
"400": {
"description": "Bad Request",
"schema": {
"$ref": "#/definitions/response.ErrorResponse"
}
},
"404": {
"description": "Not Found",
"schema": {
"$ref": "#/definitions/response.ErrorResponse"
}
},
"500": {
"description": "Internal Server Error",
"schema": {
"$ref": "#/definitions/response.ErrorResponse"
}
}
}
},
"put": {
"description": "Update an existing invoice by its ID. Only non-empty fields will be updated.",
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"tags": [
"invoice"
],
"summary": "Update invoice",
"parameters": [
{
"type": "integer",
"description": "Invoice ID",
"name": "id",
"in": "path",
"required": true
},
{
"description": "Invoice request body",
"name": "body",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/requests.UpdateInvoiceRequest"
}
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"allOf": [
{
"$ref": "#/definitions/response.SuccessResponse"
},
{
"type": "object",
"properties": {
"data": {
"$ref": "#/definitions/responses.UpdateInvoiceResponse"
}
}
}
]
}
},
"400": {
"description": "Bad Request",
"schema": {
"$ref": "#/definitions/response.ErrorResponse"
}
},
"404": {
"description": "Not Found",
"schema": {
"$ref": "#/definitions/response.ErrorResponse"
}
},
"500": {
"description": "Internal Server Error",
"schema": {
"$ref": "#/definitions/response.ErrorResponse"
}
}
}
},
"delete": {
"description": "Delete an invoice by its unique identifier",
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"tags": [
"invoice"
],
"summary": "Delete invoice",
"parameters": [
{
"type": "integer",
"description": "Invoice ID",
"name": "id",
"in": "path",
"required": true
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/response.SuccessResponse"
}
},
"400": {
"description": "Bad Request",
"schema": {
"$ref": "#/definitions/response.ErrorResponse"
}
},
"500": {
"description": "Internal Server Error",
"schema": {
"$ref": "#/definitions/response.ErrorResponse"
}
}
}
}
},
"/v1/rooms": { "/v1/rooms": {
"get": { "get": {
"description": "Retrieve a list of all rooms ordered by creation date", "description": "Retrieve a list of all rooms ordered by creation date",
@@ -3234,6 +3780,35 @@ const docTemplate = `{
} }
}, },
"definitions": { "definitions": {
"models.AlternativeComponent": {
"type": "object",
"properties": {
"alternativeComponentId": {
"type": "integer"
},
"conversionRatio": {
"type": "string"
},
"id": {
"type": "integer"
},
"invoiceConfigItemId": {
"type": "integer"
},
"metadata": {
"type": "array",
"items": {
"type": "integer"
}
},
"note": {
"type": "string"
},
"priority": {
"type": "integer"
}
}
},
"models.Cabinet": { "models.Cabinet": {
"type": "object", "type": "object",
"properties": { "properties": {
@@ -3452,6 +4027,53 @@ const docTemplate = `{
} }
} }
}, },
"models.Invoice": {
"type": "object",
"properties": {
"approvedBy": {
"type": "string"
},
"completedAt": {
"type": "string"
},
"createdAt": {
"type": "string"
},
"createdBy": {
"type": "string"
},
"id": {
"type": "integer"
},
"invoiceCode": {
"type": "string"
},
"invoiceConfigId": {
"type": "integer"
},
"metadata": {
"type": "array",
"items": {
"type": "integer"
}
},
"note": {
"type": "string"
},
"status": {
"type": "string"
},
"totalItems": {
"type": "integer"
},
"type": {
"type": "string"
},
"updatedAt": {
"type": "string"
}
}
},
"models.InvoiceConfig": { "models.InvoiceConfig": {
"type": "object", "type": "object",
"properties": { "properties": {
@@ -3611,6 +4233,32 @@ const docTemplate = `{
} }
} }
}, },
"requests.CreateAlternativeComponentRequest": {
"type": "object",
"required": [
"alternativeComponentId",
"conversionRatio",
"invoiceConfigItemId",
"priority"
],
"properties": {
"alternativeComponentId": {
"type": "integer"
},
"conversionRatio": {
"type": "string"
},
"invoiceConfigItemId": {
"type": "integer"
},
"note": {
"type": "string"
},
"priority": {
"type": "integer"
}
}
},
"requests.CreateCabinetRequest": { "requests.CreateCabinetRequest": {
"type": "object", "type": "object",
"required": [ "required": [
@@ -3818,6 +4466,36 @@ const docTemplate = `{
} }
} }
}, },
"requests.CreateInvoiceRequest": {
"type": "object",
"required": [
"status",
"type"
],
"properties": {
"approvedBy": {
"type": "string"
},
"createdBy": {
"type": "string"
},
"invoiceConfigId": {
"type": "integer"
},
"note": {
"type": "string"
},
"status": {
"type": "string"
},
"totalItems": {
"type": "integer"
},
"type": {
"type": "string"
}
}
},
"requests.CreateRoomRequest": { "requests.CreateRoomRequest": {
"type": "object", "type": "object",
"required": [ "required": [
@@ -3876,6 +4554,26 @@ const docTemplate = `{
} }
} }
}, },
"requests.UpdateAlternativeComponentRequest": {
"type": "object",
"properties": {
"alternativeComponentId": {
"type": "integer"
},
"conversionRatio": {
"type": "string"
},
"invoiceConfigItemId": {
"type": "integer"
},
"note": {
"type": "string"
},
"priority": {
"type": "integer"
}
}
},
"requests.UpdateCabinetRequest": { "requests.UpdateCabinetRequest": {
"type": "object", "type": "object",
"properties": { "properties": {
@@ -4051,6 +4749,26 @@ const docTemplate = `{
} }
} }
}, },
"requests.UpdateInvoiceRequest": {
"type": "object",
"properties": {
"invoiceConfigId": {
"type": "integer"
},
"note": {
"type": "string"
},
"status": {
"type": "string"
},
"totalItems": {
"type": "integer"
},
"type": {
"type": "string"
}
}
},
"requests.UpdateRoomRequest": { "requests.UpdateRoomRequest": {
"type": "object", "type": "object",
"properties": { "properties": {
@@ -4131,6 +4849,14 @@ const docTemplate = `{
} }
} }
}, },
"responses.CreateAlternativeComponentResponse": {
"type": "object",
"properties": {
"id": {
"type": "integer"
}
}
},
"responses.CreateCabinetResponse": { "responses.CreateCabinetResponse": {
"type": "object", "type": "object",
"properties": { "properties": {
@@ -4195,6 +4921,17 @@ const docTemplate = `{
} }
} }
}, },
"responses.CreateInvoiceResponse": {
"type": "object",
"properties": {
"id": {
"type": "integer"
},
"invoiceCode": {
"type": "string"
}
}
},
"responses.CreateRoomResponse": { "responses.CreateRoomResponse": {
"type": "object", "type": "object",
"properties": { "properties": {
@@ -4219,6 +4956,29 @@ const docTemplate = `{
} }
} }
}, },
"responses.UpdateAlternativeComponentResponse": {
"type": "object",
"properties": {
"alternativeComponentId": {
"type": "integer"
},
"conversionRatio": {
"type": "string"
},
"id": {
"type": "integer"
},
"invoiceConfigItemId": {
"type": "integer"
},
"note": {
"type": "string"
},
"priority": {
"type": "integer"
}
}
},
"responses.UpdateCabinetResponse": { "responses.UpdateCabinetResponse": {
"type": "object", "type": "object",
"properties": { "properties": {
@@ -4420,6 +5180,32 @@ const docTemplate = `{
} }
} }
}, },
"responses.UpdateInvoiceResponse": {
"type": "object",
"properties": {
"id": {
"type": "integer"
},
"invoiceCode": {
"type": "string"
},
"invoiceConfigId": {
"type": "integer"
},
"note": {
"type": "string"
},
"status": {
"type": "string"
},
"totalItems": {
"type": "integer"
},
"type": {
"type": "string"
}
}
},
"responses.UpdateRoomResponse": { "responses.UpdateRoomResponse": {
"type": "object", "type": "object",
"properties": { "properties": {

View File

@@ -1321,6 +1321,279 @@
} }
} }
}, },
"/v1/alternative-components": {
"get": {
"description": "Retrieve a list of all alternative components",
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"tags": [
"alternative-component"
],
"summary": "List all alternative components",
"responses": {
"200": {
"description": "OK",
"schema": {
"allOf": [
{
"$ref": "#/definitions/response.SuccessResponse"
},
{
"type": "object",
"properties": {
"data": {
"type": "array",
"items": {
"$ref": "#/definitions/models.AlternativeComponent"
}
}
}
}
]
}
},
"500": {
"description": "Internal Server Error",
"schema": {
"$ref": "#/definitions/response.ErrorResponse"
}
}
}
},
"post": {
"description": "Create a new alternative component with the provided details",
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"tags": [
"alternative-component"
],
"summary": "Create a new alternative component",
"parameters": [
{
"description": "Alternative component request body",
"name": "body",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/requests.CreateAlternativeComponentRequest"
}
}
],
"responses": {
"201": {
"description": "Created",
"schema": {
"allOf": [
{
"$ref": "#/definitions/response.SuccessResponse"
},
{
"type": "object",
"properties": {
"data": {
"$ref": "#/definitions/responses.CreateAlternativeComponentResponse"
}
}
}
]
}
},
"400": {
"description": "Bad Request",
"schema": {
"$ref": "#/definitions/response.ErrorResponse"
}
},
"500": {
"description": "Internal Server Error",
"schema": {
"$ref": "#/definitions/response.ErrorResponse"
}
}
}
}
},
"/v1/alternative-components/{id}": {
"get": {
"description": "Retrieve a single alternative component using its unique identifier",
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"tags": [
"alternative-component"
],
"summary": "Get alternative component by ID",
"parameters": [
{
"type": "integer",
"description": "Alternative component ID",
"name": "id",
"in": "path",
"required": true
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"allOf": [
{
"$ref": "#/definitions/response.SuccessResponse"
},
{
"type": "object",
"properties": {
"data": {
"$ref": "#/definitions/models.AlternativeComponent"
}
}
}
]
}
},
"400": {
"description": "Bad Request",
"schema": {
"$ref": "#/definitions/response.ErrorResponse"
}
},
"404": {
"description": "Not Found",
"schema": {
"$ref": "#/definitions/response.ErrorResponse"
}
},
"500": {
"description": "Internal Server Error",
"schema": {
"$ref": "#/definitions/response.ErrorResponse"
}
}
}
},
"put": {
"description": "Update an existing alternative component by its ID. Only non-empty fields will be updated.",
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"tags": [
"alternative-component"
],
"summary": "Update alternative component",
"parameters": [
{
"type": "integer",
"description": "Alternative component ID",
"name": "id",
"in": "path",
"required": true
},
{
"description": "Alternative component request body",
"name": "body",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/requests.UpdateAlternativeComponentRequest"
}
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"allOf": [
{
"$ref": "#/definitions/response.SuccessResponse"
},
{
"type": "object",
"properties": {
"data": {
"$ref": "#/definitions/responses.UpdateAlternativeComponentResponse"
}
}
}
]
}
},
"400": {
"description": "Bad Request",
"schema": {
"$ref": "#/definitions/response.ErrorResponse"
}
},
"404": {
"description": "Not Found",
"schema": {
"$ref": "#/definitions/response.ErrorResponse"
}
},
"500": {
"description": "Internal Server Error",
"schema": {
"$ref": "#/definitions/response.ErrorResponse"
}
}
}
},
"delete": {
"description": "Delete an alternative component by its unique identifier",
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"tags": [
"alternative-component"
],
"summary": "Delete alternative component",
"parameters": [
{
"type": "integer",
"description": "Alternative component ID",
"name": "id",
"in": "path",
"required": true
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/response.SuccessResponse"
}
},
"400": {
"description": "Bad Request",
"schema": {
"$ref": "#/definitions/response.ErrorResponse"
}
},
"500": {
"description": "Internal Server Error",
"schema": {
"$ref": "#/definitions/response.ErrorResponse"
}
}
}
}
},
"/v1/cabinets": { "/v1/cabinets": {
"get": { "get": {
"description": "Retrieve a list of all cabinets ordered by creation date", "description": "Retrieve a list of all cabinets ordered by creation date",
@@ -2413,6 +2686,279 @@
} }
} }
}, },
"/v1/invoices": {
"get": {
"description": "Retrieve a list of all invoices ordered by creation date",
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"tags": [
"invoice"
],
"summary": "List all invoices",
"responses": {
"200": {
"description": "OK",
"schema": {
"allOf": [
{
"$ref": "#/definitions/response.SuccessResponse"
},
{
"type": "object",
"properties": {
"data": {
"type": "array",
"items": {
"$ref": "#/definitions/models.Invoice"
}
}
}
}
]
}
},
"500": {
"description": "Internal Server Error",
"schema": {
"$ref": "#/definitions/response.ErrorResponse"
}
}
}
},
"post": {
"description": "Create a new invoice with the provided details",
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"tags": [
"invoice"
],
"summary": "Create a new invoice",
"parameters": [
{
"description": "Invoice request body",
"name": "body",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/requests.CreateInvoiceRequest"
}
}
],
"responses": {
"201": {
"description": "Created",
"schema": {
"allOf": [
{
"$ref": "#/definitions/response.SuccessResponse"
},
{
"type": "object",
"properties": {
"data": {
"$ref": "#/definitions/responses.CreateInvoiceResponse"
}
}
}
]
}
},
"400": {
"description": "Bad Request",
"schema": {
"$ref": "#/definitions/response.ErrorResponse"
}
},
"500": {
"description": "Internal Server Error",
"schema": {
"$ref": "#/definitions/response.ErrorResponse"
}
}
}
}
},
"/v1/invoices/{id}": {
"get": {
"description": "Retrieve a single invoice using its unique identifier",
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"tags": [
"invoice"
],
"summary": "Get invoice by ID",
"parameters": [
{
"type": "integer",
"description": "Invoice ID",
"name": "id",
"in": "path",
"required": true
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"allOf": [
{
"$ref": "#/definitions/response.SuccessResponse"
},
{
"type": "object",
"properties": {
"data": {
"$ref": "#/definitions/models.Invoice"
}
}
}
]
}
},
"400": {
"description": "Bad Request",
"schema": {
"$ref": "#/definitions/response.ErrorResponse"
}
},
"404": {
"description": "Not Found",
"schema": {
"$ref": "#/definitions/response.ErrorResponse"
}
},
"500": {
"description": "Internal Server Error",
"schema": {
"$ref": "#/definitions/response.ErrorResponse"
}
}
}
},
"put": {
"description": "Update an existing invoice by its ID. Only non-empty fields will be updated.",
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"tags": [
"invoice"
],
"summary": "Update invoice",
"parameters": [
{
"type": "integer",
"description": "Invoice ID",
"name": "id",
"in": "path",
"required": true
},
{
"description": "Invoice request body",
"name": "body",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/requests.UpdateInvoiceRequest"
}
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"allOf": [
{
"$ref": "#/definitions/response.SuccessResponse"
},
{
"type": "object",
"properties": {
"data": {
"$ref": "#/definitions/responses.UpdateInvoiceResponse"
}
}
}
]
}
},
"400": {
"description": "Bad Request",
"schema": {
"$ref": "#/definitions/response.ErrorResponse"
}
},
"404": {
"description": "Not Found",
"schema": {
"$ref": "#/definitions/response.ErrorResponse"
}
},
"500": {
"description": "Internal Server Error",
"schema": {
"$ref": "#/definitions/response.ErrorResponse"
}
}
}
},
"delete": {
"description": "Delete an invoice by its unique identifier",
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"tags": [
"invoice"
],
"summary": "Delete invoice",
"parameters": [
{
"type": "integer",
"description": "Invoice ID",
"name": "id",
"in": "path",
"required": true
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/response.SuccessResponse"
}
},
"400": {
"description": "Bad Request",
"schema": {
"$ref": "#/definitions/response.ErrorResponse"
}
},
"500": {
"description": "Internal Server Error",
"schema": {
"$ref": "#/definitions/response.ErrorResponse"
}
}
}
}
},
"/v1/rooms": { "/v1/rooms": {
"get": { "get": {
"description": "Retrieve a list of all rooms ordered by creation date", "description": "Retrieve a list of all rooms ordered by creation date",
@@ -3228,6 +3774,35 @@
} }
}, },
"definitions": { "definitions": {
"models.AlternativeComponent": {
"type": "object",
"properties": {
"alternativeComponentId": {
"type": "integer"
},
"conversionRatio": {
"type": "string"
},
"id": {
"type": "integer"
},
"invoiceConfigItemId": {
"type": "integer"
},
"metadata": {
"type": "array",
"items": {
"type": "integer"
}
},
"note": {
"type": "string"
},
"priority": {
"type": "integer"
}
}
},
"models.Cabinet": { "models.Cabinet": {
"type": "object", "type": "object",
"properties": { "properties": {
@@ -3446,6 +4021,53 @@
} }
} }
}, },
"models.Invoice": {
"type": "object",
"properties": {
"approvedBy": {
"type": "string"
},
"completedAt": {
"type": "string"
},
"createdAt": {
"type": "string"
},
"createdBy": {
"type": "string"
},
"id": {
"type": "integer"
},
"invoiceCode": {
"type": "string"
},
"invoiceConfigId": {
"type": "integer"
},
"metadata": {
"type": "array",
"items": {
"type": "integer"
}
},
"note": {
"type": "string"
},
"status": {
"type": "string"
},
"totalItems": {
"type": "integer"
},
"type": {
"type": "string"
},
"updatedAt": {
"type": "string"
}
}
},
"models.InvoiceConfig": { "models.InvoiceConfig": {
"type": "object", "type": "object",
"properties": { "properties": {
@@ -3605,6 +4227,32 @@
} }
} }
}, },
"requests.CreateAlternativeComponentRequest": {
"type": "object",
"required": [
"alternativeComponentId",
"conversionRatio",
"invoiceConfigItemId",
"priority"
],
"properties": {
"alternativeComponentId": {
"type": "integer"
},
"conversionRatio": {
"type": "string"
},
"invoiceConfigItemId": {
"type": "integer"
},
"note": {
"type": "string"
},
"priority": {
"type": "integer"
}
}
},
"requests.CreateCabinetRequest": { "requests.CreateCabinetRequest": {
"type": "object", "type": "object",
"required": [ "required": [
@@ -3812,6 +4460,36 @@
} }
} }
}, },
"requests.CreateInvoiceRequest": {
"type": "object",
"required": [
"status",
"type"
],
"properties": {
"approvedBy": {
"type": "string"
},
"createdBy": {
"type": "string"
},
"invoiceConfigId": {
"type": "integer"
},
"note": {
"type": "string"
},
"status": {
"type": "string"
},
"totalItems": {
"type": "integer"
},
"type": {
"type": "string"
}
}
},
"requests.CreateRoomRequest": { "requests.CreateRoomRequest": {
"type": "object", "type": "object",
"required": [ "required": [
@@ -3870,6 +4548,26 @@
} }
} }
}, },
"requests.UpdateAlternativeComponentRequest": {
"type": "object",
"properties": {
"alternativeComponentId": {
"type": "integer"
},
"conversionRatio": {
"type": "string"
},
"invoiceConfigItemId": {
"type": "integer"
},
"note": {
"type": "string"
},
"priority": {
"type": "integer"
}
}
},
"requests.UpdateCabinetRequest": { "requests.UpdateCabinetRequest": {
"type": "object", "type": "object",
"properties": { "properties": {
@@ -4045,6 +4743,26 @@
} }
} }
}, },
"requests.UpdateInvoiceRequest": {
"type": "object",
"properties": {
"invoiceConfigId": {
"type": "integer"
},
"note": {
"type": "string"
},
"status": {
"type": "string"
},
"totalItems": {
"type": "integer"
},
"type": {
"type": "string"
}
}
},
"requests.UpdateRoomRequest": { "requests.UpdateRoomRequest": {
"type": "object", "type": "object",
"properties": { "properties": {
@@ -4125,6 +4843,14 @@
} }
} }
}, },
"responses.CreateAlternativeComponentResponse": {
"type": "object",
"properties": {
"id": {
"type": "integer"
}
}
},
"responses.CreateCabinetResponse": { "responses.CreateCabinetResponse": {
"type": "object", "type": "object",
"properties": { "properties": {
@@ -4189,6 +4915,17 @@
} }
} }
}, },
"responses.CreateInvoiceResponse": {
"type": "object",
"properties": {
"id": {
"type": "integer"
},
"invoiceCode": {
"type": "string"
}
}
},
"responses.CreateRoomResponse": { "responses.CreateRoomResponse": {
"type": "object", "type": "object",
"properties": { "properties": {
@@ -4213,6 +4950,29 @@
} }
} }
}, },
"responses.UpdateAlternativeComponentResponse": {
"type": "object",
"properties": {
"alternativeComponentId": {
"type": "integer"
},
"conversionRatio": {
"type": "string"
},
"id": {
"type": "integer"
},
"invoiceConfigItemId": {
"type": "integer"
},
"note": {
"type": "string"
},
"priority": {
"type": "integer"
}
}
},
"responses.UpdateCabinetResponse": { "responses.UpdateCabinetResponse": {
"type": "object", "type": "object",
"properties": { "properties": {
@@ -4414,6 +5174,32 @@
} }
} }
}, },
"responses.UpdateInvoiceResponse": {
"type": "object",
"properties": {
"id": {
"type": "integer"
},
"invoiceCode": {
"type": "string"
},
"invoiceConfigId": {
"type": "integer"
},
"note": {
"type": "string"
},
"status": {
"type": "string"
},
"totalItems": {
"type": "integer"
},
"type": {
"type": "string"
}
}
},
"responses.UpdateRoomResponse": { "responses.UpdateRoomResponse": {
"type": "object", "type": "object",
"properties": { "properties": {

View File

@@ -1,5 +1,24 @@
basePath: /api/v1 basePath: /api/v1
definitions: definitions:
models.AlternativeComponent:
properties:
alternativeComponentId:
type: integer
conversionRatio:
type: string
id:
type: integer
invoiceConfigItemId:
type: integer
metadata:
items:
type: integer
type: array
note:
type: string
priority:
type: integer
type: object
models.Cabinet: models.Cabinet:
properties: properties:
createdAt: createdAt:
@@ -143,6 +162,37 @@ definitions:
warehouseName: warehouseName:
type: string type: string
type: object type: object
models.Invoice:
properties:
approvedBy:
type: string
completedAt:
type: string
createdAt:
type: string
createdBy:
type: string
id:
type: integer
invoiceCode:
type: string
invoiceConfigId:
type: integer
metadata:
items:
type: integer
type: array
note:
type: string
status:
type: string
totalItems:
type: integer
type:
type: string
updatedAt:
type: string
type: object
models.InvoiceConfig: models.InvoiceConfig:
properties: properties:
createdAt: createdAt:
@@ -248,6 +298,24 @@ definitions:
- password - password
- username - username
type: object type: object
requests.CreateAlternativeComponentRequest:
properties:
alternativeComponentId:
type: integer
conversionRatio:
type: string
invoiceConfigItemId:
type: integer
note:
type: string
priority:
type: integer
required:
- alternativeComponentId
- conversionRatio
- invoiceConfigItemId
- priority
type: object
requests.CreateCabinetRequest: requests.CreateCabinetRequest:
properties: properties:
description: description:
@@ -388,6 +456,26 @@ definitions:
- name - name
- type - type
type: object type: object
requests.CreateInvoiceRequest:
properties:
approvedBy:
type: string
createdBy:
type: string
invoiceConfigId:
type: integer
note:
type: string
status:
type: string
totalItems:
type: integer
type:
type: string
required:
- status
- type
type: object
requests.CreateRoomRequest: requests.CreateRoomRequest:
properties: properties:
description: description:
@@ -427,6 +515,19 @@ definitions:
- address - address
- name - name
type: object type: object
requests.UpdateAlternativeComponentRequest:
properties:
alternativeComponentId:
type: integer
conversionRatio:
type: string
invoiceConfigItemId:
type: integer
note:
type: string
priority:
type: integer
type: object
requests.UpdateCabinetRequest: requests.UpdateCabinetRequest:
properties: properties:
description: description:
@@ -542,6 +643,19 @@ definitions:
type: type:
type: string type: string
type: object type: object
requests.UpdateInvoiceRequest:
properties:
invoiceConfigId:
type: integer
note:
type: string
status:
type: string
totalItems:
type: integer
type:
type: string
type: object
requests.UpdateRoomRequest: requests.UpdateRoomRequest:
properties: properties:
description: description:
@@ -594,6 +708,11 @@ definitions:
id: id:
type: string type: string
type: object type: object
responses.CreateAlternativeComponentResponse:
properties:
id:
type: integer
type: object
responses.CreateCabinetResponse: responses.CreateCabinetResponse:
properties: properties:
id: id:
@@ -634,6 +753,13 @@ definitions:
id: id:
type: integer type: integer
type: object type: object
responses.CreateInvoiceResponse:
properties:
id:
type: integer
invoiceCode:
type: string
type: object
responses.CreateRoomResponse: responses.CreateRoomResponse:
properties: properties:
id: id:
@@ -649,6 +775,21 @@ definitions:
id: id:
type: integer type: integer
type: object type: object
responses.UpdateAlternativeComponentResponse:
properties:
alternativeComponentId:
type: integer
conversionRatio:
type: string
id:
type: integer
invoiceConfigItemId:
type: integer
note:
type: string
priority:
type: integer
type: object
responses.UpdateCabinetResponse: responses.UpdateCabinetResponse:
properties: properties:
description: description:
@@ -780,6 +921,23 @@ definitions:
type: type:
type: string type: string
type: object type: object
responses.UpdateInvoiceResponse:
properties:
id:
type: integer
invoiceCode:
type: string
invoiceConfigId:
type: integer
note:
type: string
status:
type: string
totalItems:
type: integer
type:
type: string
type: object
responses.UpdateRoomResponse: responses.UpdateRoomResponse:
properties: properties:
description: description:
@@ -1642,6 +1800,176 @@ paths:
summary: Health check summary: Health check
tags: tags:
- health - health
/v1/alternative-components:
get:
consumes:
- application/json
description: Retrieve a list of all alternative components
produces:
- application/json
responses:
"200":
description: OK
schema:
allOf:
- $ref: '#/definitions/response.SuccessResponse'
- properties:
data:
items:
$ref: '#/definitions/models.AlternativeComponent'
type: array
type: object
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/response.ErrorResponse'
summary: List all alternative components
tags:
- alternative-component
post:
consumes:
- application/json
description: Create a new alternative component with the provided details
parameters:
- description: Alternative component request body
in: body
name: body
required: true
schema:
$ref: '#/definitions/requests.CreateAlternativeComponentRequest'
produces:
- application/json
responses:
"201":
description: Created
schema:
allOf:
- $ref: '#/definitions/response.SuccessResponse'
- properties:
data:
$ref: '#/definitions/responses.CreateAlternativeComponentResponse'
type: object
"400":
description: Bad Request
schema:
$ref: '#/definitions/response.ErrorResponse'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/response.ErrorResponse'
summary: Create a new alternative component
tags:
- alternative-component
/v1/alternative-components/{id}:
delete:
consumes:
- application/json
description: Delete an alternative component by its unique identifier
parameters:
- description: Alternative component ID
in: path
name: id
required: true
type: integer
produces:
- application/json
responses:
"200":
description: OK
schema:
$ref: '#/definitions/response.SuccessResponse'
"400":
description: Bad Request
schema:
$ref: '#/definitions/response.ErrorResponse'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/response.ErrorResponse'
summary: Delete alternative component
tags:
- alternative-component
get:
consumes:
- application/json
description: Retrieve a single alternative component using its unique identifier
parameters:
- description: Alternative component ID
in: path
name: id
required: true
type: integer
produces:
- application/json
responses:
"200":
description: OK
schema:
allOf:
- $ref: '#/definitions/response.SuccessResponse'
- properties:
data:
$ref: '#/definitions/models.AlternativeComponent'
type: object
"400":
description: Bad Request
schema:
$ref: '#/definitions/response.ErrorResponse'
"404":
description: Not Found
schema:
$ref: '#/definitions/response.ErrorResponse'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/response.ErrorResponse'
summary: Get alternative component by ID
tags:
- alternative-component
put:
consumes:
- application/json
description: Update an existing alternative component by its ID. Only non-empty
fields will be updated.
parameters:
- description: Alternative component ID
in: path
name: id
required: true
type: integer
- description: Alternative component request body
in: body
name: body
required: true
schema:
$ref: '#/definitions/requests.UpdateAlternativeComponentRequest'
produces:
- application/json
responses:
"200":
description: OK
schema:
allOf:
- $ref: '#/definitions/response.SuccessResponse'
- properties:
data:
$ref: '#/definitions/responses.UpdateAlternativeComponentResponse'
type: object
"400":
description: Bad Request
schema:
$ref: '#/definitions/response.ErrorResponse'
"404":
description: Not Found
schema:
$ref: '#/definitions/response.ErrorResponse'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/response.ErrorResponse'
summary: Update alternative component
tags:
- alternative-component
/v1/cabinets: /v1/cabinets:
get: get:
consumes: consumes:
@@ -2322,6 +2650,176 @@ paths:
summary: Update invoice config summary: Update invoice config
tags: tags:
- invoice-config - invoice-config
/v1/invoices:
get:
consumes:
- application/json
description: Retrieve a list of all invoices ordered by creation date
produces:
- application/json
responses:
"200":
description: OK
schema:
allOf:
- $ref: '#/definitions/response.SuccessResponse'
- properties:
data:
items:
$ref: '#/definitions/models.Invoice'
type: array
type: object
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/response.ErrorResponse'
summary: List all invoices
tags:
- invoice
post:
consumes:
- application/json
description: Create a new invoice with the provided details
parameters:
- description: Invoice request body
in: body
name: body
required: true
schema:
$ref: '#/definitions/requests.CreateInvoiceRequest'
produces:
- application/json
responses:
"201":
description: Created
schema:
allOf:
- $ref: '#/definitions/response.SuccessResponse'
- properties:
data:
$ref: '#/definitions/responses.CreateInvoiceResponse'
type: object
"400":
description: Bad Request
schema:
$ref: '#/definitions/response.ErrorResponse'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/response.ErrorResponse'
summary: Create a new invoice
tags:
- invoice
/v1/invoices/{id}:
delete:
consumes:
- application/json
description: Delete an invoice by its unique identifier
parameters:
- description: Invoice ID
in: path
name: id
required: true
type: integer
produces:
- application/json
responses:
"200":
description: OK
schema:
$ref: '#/definitions/response.SuccessResponse'
"400":
description: Bad Request
schema:
$ref: '#/definitions/response.ErrorResponse'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/response.ErrorResponse'
summary: Delete invoice
tags:
- invoice
get:
consumes:
- application/json
description: Retrieve a single invoice using its unique identifier
parameters:
- description: Invoice ID
in: path
name: id
required: true
type: integer
produces:
- application/json
responses:
"200":
description: OK
schema:
allOf:
- $ref: '#/definitions/response.SuccessResponse'
- properties:
data:
$ref: '#/definitions/models.Invoice'
type: object
"400":
description: Bad Request
schema:
$ref: '#/definitions/response.ErrorResponse'
"404":
description: Not Found
schema:
$ref: '#/definitions/response.ErrorResponse'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/response.ErrorResponse'
summary: Get invoice by ID
tags:
- invoice
put:
consumes:
- application/json
description: Update an existing invoice by its ID. Only non-empty fields will
be updated.
parameters:
- description: Invoice ID
in: path
name: id
required: true
type: integer
- description: Invoice request body
in: body
name: body
required: true
schema:
$ref: '#/definitions/requests.UpdateInvoiceRequest'
produces:
- application/json
responses:
"200":
description: OK
schema:
allOf:
- $ref: '#/definitions/response.SuccessResponse'
- properties:
data:
$ref: '#/definitions/responses.UpdateInvoiceResponse'
type: object
"400":
description: Bad Request
schema:
$ref: '#/definitions/response.ErrorResponse'
"404":
description: Not Found
schema:
$ref: '#/definitions/response.ErrorResponse'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/response.ErrorResponse'
summary: Update invoice
tags:
- invoice
/v1/rooms: /v1/rooms:
get: get:
consumes: consumes:

View File

@@ -0,0 +1,67 @@
package mapper
import (
"encoding/json"
"wm-backend/internal/models"
db "wm-backend/sqlc_gen"
"github.com/jackc/pgx/v5/pgtype"
)
func numericToString(n pgtype.Numeric) string {
if !n.Valid {
return ""
}
b, _ := json.Marshal(n)
return string(b)
}
func stringToNumeric(s string) pgtype.Numeric {
var n pgtype.Numeric
if s == "" {
return n
}
_ = json.Unmarshal([]byte(s), &n)
return n
}
func ToDomainAlternativeComponent(r db.AlternativeComponent) *models.AlternativeComponent {
return &models.AlternativeComponent{
ID: r.ID,
InvoiceConfigItemID: r.InvoiceConfigItemID,
AlternativeComponentID: r.AlternativeComponentID,
ConversionRatio: numericToString(r.ConversionRatio),
Priority: r.Priority,
Note: r.Note.String,
Metadata: r.Metadata,
}
}
func ToModelAlternativeComponent(r *models.AlternativeComponent) *db.CreateAlternativeComponentParams {
return &db.CreateAlternativeComponentParams{
InvoiceConfigItemID: r.InvoiceConfigItemID,
AlternativeComponentID: r.AlternativeComponentID,
ConversionRatio: stringToNumeric(r.ConversionRatio),
Priority: r.Priority,
Note: pgtype.Text{
String: r.Note,
Valid: r.Note != "",
},
Metadata: r.Metadata,
}
}
func ToUpdateModelAlternativeComponent(r *models.AlternativeComponent) *db.UpdateAlternativeComponentParams {
return &db.UpdateAlternativeComponentParams{
InvoiceConfigItemID: r.InvoiceConfigItemID,
AlternativeComponentID: r.AlternativeComponentID,
ConversionRatio: stringToNumeric(r.ConversionRatio),
Priority: r.Priority,
Note: pgtype.Text{
String: r.Note,
Valid: r.Note != "",
},
Metadata: r.Metadata,
ID: r.ID,
}
}

View File

@@ -0,0 +1,78 @@
package mapper
import (
"wm-backend/internal/models"
db "wm-backend/sqlc_gen"
"github.com/jackc/pgx/v5/pgtype"
)
func timestampToTime(t pgtype.Timestamptz) string {
if !t.Valid {
return ""
}
return t.Time.String()
}
func ToDomainInvoice(r db.Invoice) *models.Invoice {
return &models.Invoice{
ID: r.ID,
InvoiceCode: r.InvoiceCode,
Type: string(r.Type),
Status: string(r.Status),
InvoiceConfigID: r.InvoiceConfigID.Int64,
TotalItems: r.TotalItems,
Note: r.Note.String,
CreatedBy: r.CreatedBy.String,
ApprovedBy: r.ApprovedBy.String,
CompletedAt: r.CompletedAt.Time,
CreatedAt: r.CreatedAt,
UpdatedAt: r.UpdatedAt,
Metadata: r.Metadata,
}
}
func ToModelInvoice(r *models.Invoice) *db.CreateInvoiceParams {
return &db.CreateInvoiceParams{
Type: db.InvoiceTypeEnum(r.Type),
Status: db.InvoiceStatusEnum(r.Status),
InvoiceConfigID: pgtype.Int8{
Int64: r.InvoiceConfigID,
Valid: r.InvoiceConfigID != 0,
},
TotalItems: r.TotalItems,
Note: pgtype.Text{
String: r.Note,
Valid: r.Note != "",
},
CreatedBy: pgtype.Text{
String: r.CreatedBy,
Valid: r.CreatedBy != "",
},
ApprovedBy: pgtype.Text{
String: r.ApprovedBy,
Valid: r.ApprovedBy != "",
},
CreatedAt: r.CreatedAt,
Metadata: r.Metadata,
}
}
func ToUpdateModelInvoice(r *models.Invoice) *db.UpdateInvoiceParams {
return &db.UpdateInvoiceParams{
Type: db.InvoiceTypeEnum(r.Type),
Status: db.InvoiceStatusEnum(r.Status),
InvoiceConfigID: pgtype.Int8{
Int64: r.InvoiceConfigID,
Valid: r.InvoiceConfigID != 0,
},
TotalItems: r.TotalItems,
Note: pgtype.Text{
String: r.Note,
Valid: r.Note != "",
},
Metadata: r.Metadata,
UpdatedAt: r.UpdatedAt,
ID: r.ID,
}
}

View File

@@ -0,0 +1,11 @@
package models
type AlternativeComponent struct {
ID int64 `json:"id"`
InvoiceConfigItemID int64 `json:"invoiceConfigItemId"`
AlternativeComponentID int64 `json:"alternativeComponentId"`
ConversionRatio string `json:"conversionRatio"`
Priority int32 `json:"priority"`
Note string `json:"note"`
Metadata []byte `json:"metadata"`
}

View File

@@ -0,0 +1,19 @@
package models
import "time"
type Invoice struct {
ID int64 `json:"id"`
InvoiceCode string `json:"invoiceCode"`
Type string `json:"type"`
Status string `json:"status"`
InvoiceConfigID int64 `json:"invoiceConfigId"`
TotalItems int32 `json:"totalItems"`
Note string `json:"note"`
CreatedBy string `json:"createdBy"`
ApprovedBy string `json:"approvedBy"`
CompletedAt time.Time `json:"completedAt"`
CreatedAt time.Time `json:"createdAt"`
UpdatedAt time.Time `json:"updatedAt"`
Metadata []byte `json:"metadata"`
}

View File

@@ -0,0 +1,17 @@
package requests
type CreateAlternativeComponentRequest struct {
InvoiceConfigItemID int64 `json:"invoiceConfigItemId" binding:"required"`
AlternativeComponentID int64 `json:"alternativeComponentId" binding:"required"`
ConversionRatio string `json:"conversionRatio" binding:"required"`
Priority int32 `json:"priority" binding:"required"`
Note string `json:"note"`
}
type UpdateAlternativeComponentRequest struct {
InvoiceConfigItemID *int64 `json:"invoiceConfigItemId"`
AlternativeComponentID *int64 `json:"alternativeComponentId"`
ConversionRatio *string `json:"conversionRatio"`
Priority *int32 `json:"priority"`
Note string `json:"note"`
}

View File

@@ -0,0 +1,19 @@
package requests
type CreateInvoiceRequest struct {
Type string `json:"type" binding:"required"`
Status string `json:"status" binding:"required"`
InvoiceConfigID int64 `json:"invoiceConfigId"`
TotalItems int32 `json:"totalItems"`
Note string `json:"note"`
CreatedBy string `json:"createdBy"`
ApprovedBy string `json:"approvedBy"`
}
type UpdateInvoiceRequest struct {
Type *string `json:"type"`
Status *string `json:"status"`
InvoiceConfigID *int64 `json:"invoiceConfigId"`
TotalItems *int32 `json:"totalItems"`
Note string `json:"note"`
}

View File

@@ -0,0 +1,14 @@
package responses
type CreateAlternativeComponentResponse struct {
ID int64 `json:"id"`
}
type UpdateAlternativeComponentResponse struct {
ID int64 `json:"id"`
InvoiceConfigItemID int64 `json:"invoiceConfigItemId"`
AlternativeComponentID int64 `json:"alternativeComponentId"`
ConversionRatio string `json:"conversionRatio"`
Priority int32 `json:"priority"`
Note string `json:"note"`
}

View File

@@ -0,0 +1,16 @@
package responses
type CreateInvoiceResponse struct {
ID int64 `json:"id"`
InvoiceCode string `json:"invoiceCode"`
}
type UpdateInvoiceResponse struct {
ID int64 `json:"id"`
InvoiceCode string `json:"invoiceCode"`
Type string `json:"type"`
Status string `json:"status"`
InvoiceConfigID int64 `json:"invoiceConfigId"`
TotalItems int32 `json:"totalItems"`
Note string `json:"note"`
}

View File

@@ -0,0 +1,52 @@
package repositories
import (
"context"
"wm-backend/internal/mapper"
"wm-backend/internal/models"
db "wm-backend/sqlc_gen"
)
func CreateAlternativeComponent(ctx context.Context, queries *db.Queries, body models.AlternativeComponent) (models.AlternativeComponent, error) {
result, err := queries.CreateAlternativeComponent(ctx, *mapper.ToModelAlternativeComponent(&body))
if err != nil {
return models.AlternativeComponent{}, err
}
return *mapper.ToDomainAlternativeComponent(result), nil
}
func GetAlternativeComponentByID(ctx context.Context, queries *db.Queries, id int64) (models.AlternativeComponent, error) {
result, err := queries.GetAlternativeComponentByID(ctx, id)
if err != nil {
return models.AlternativeComponent{}, err
}
return *mapper.ToDomainAlternativeComponent(result), nil
}
func ListAlternativeComponents(ctx context.Context, queries *db.Queries) ([]models.AlternativeComponent, error) {
results, err := queries.ListAlternativeComponents(ctx)
if err != nil {
return nil, err
}
var items []models.AlternativeComponent
for _, r := range results {
items = append(items, *mapper.ToDomainAlternativeComponent(r))
}
return items, nil
}
func UpdateAlternativeComponent(ctx context.Context, queries *db.Queries, body models.AlternativeComponent) (models.AlternativeComponent, error) {
result, err := queries.UpdateAlternativeComponent(ctx, *mapper.ToUpdateModelAlternativeComponent(&body))
if err != nil {
return models.AlternativeComponent{}, err
}
return *mapper.ToDomainAlternativeComponent(result), nil
}
func DeleteAlternativeComponent(ctx context.Context, queries *db.Queries, id int64) (int64, error) {
rowsAffected, err := queries.DeleteAlternativeComponent(ctx, id)
if err != nil {
return rowsAffected, err
}
return rowsAffected, nil
}

View File

@@ -0,0 +1,52 @@
package repositories
import (
"context"
"wm-backend/internal/mapper"
"wm-backend/internal/models"
db "wm-backend/sqlc_gen"
)
func CreateInvoice(ctx context.Context, queries *db.Queries, body models.Invoice) (models.Invoice, error) {
result, err := queries.CreateInvoice(ctx, *mapper.ToModelInvoice(&body))
if err != nil {
return models.Invoice{}, err
}
return *mapper.ToDomainInvoice(result), nil
}
func GetInvoiceByID(ctx context.Context, queries *db.Queries, id int64) (models.Invoice, error) {
result, err := queries.GetInvoiceByID(ctx, id)
if err != nil {
return models.Invoice{}, err
}
return *mapper.ToDomainInvoice(result), nil
}
func ListInvoices(ctx context.Context, queries *db.Queries) ([]models.Invoice, error) {
results, err := queries.ListInvoices(ctx)
if err != nil {
return nil, err
}
var items []models.Invoice
for _, r := range results {
items = append(items, *mapper.ToDomainInvoice(r))
}
return items, nil
}
func UpdateInvoice(ctx context.Context, queries *db.Queries, body models.Invoice) (models.Invoice, error) {
result, err := queries.UpdateInvoice(ctx, *mapper.ToUpdateModelInvoice(&body))
if err != nil {
return models.Invoice{}, err
}
return *mapper.ToDomainInvoice(result), nil
}
func DeleteInvoice(ctx context.Context, queries *db.Queries, id int64) (int64, error) {
rowsAffected, err := queries.DeleteInvoice(ctx, id)
if err != nil {
return rowsAffected, err
}
return rowsAffected, nil
}

View File

@@ -129,6 +129,24 @@ func NewRouter() *gin.Engine {
invoiceConfigItem.PUT("/:id", utils.AsyncHandler(services.InvoiceConfigItemUpdate)) invoiceConfigItem.PUT("/:id", utils.AsyncHandler(services.InvoiceConfigItemUpdate))
invoiceConfigItem.DELETE("/:id", utils.AsyncHandler(services.InvoiceConfigItemDelete)) invoiceConfigItem.DELETE("/:id", utils.AsyncHandler(services.InvoiceConfigItemDelete))
} }
invoice := v1.Group(constants.API_GROUP_INVOICE)
{
invoice.GET("", utils.AsyncHandler(services.InvoiceList))
invoice.GET("/:id", utils.AsyncHandler(services.InvoiceGetByID))
invoice.POST("", utils.AsyncHandler(services.InvoiceCreate))
invoice.PUT("/:id", utils.AsyncHandler(services.InvoiceUpdate))
invoice.DELETE("/:id", utils.AsyncHandler(services.InvoiceDelete))
}
alternativeComponent := v1.Group(constants.API_GROUP_ALTERNATIVE_COMPONENT)
{
alternativeComponent.GET("", utils.AsyncHandler(services.AlternativeComponentList))
alternativeComponent.GET("/:id", utils.AsyncHandler(services.AlternativeComponentGetByID))
alternativeComponent.POST("", utils.AsyncHandler(services.AlternativeComponentCreate))
alternativeComponent.PUT("/:id", utils.AsyncHandler(services.AlternativeComponentUpdate))
alternativeComponent.DELETE("/:id", utils.AsyncHandler(services.AlternativeComponentDelete))
}
} }
r.GET(constants.API_PATH_PING, services.PingHandler) r.GET(constants.API_PATH_PING, services.PingHandler)

View File

@@ -0,0 +1,194 @@
package services
import (
"net/http"
"strconv"
"wm-backend/global"
"wm-backend/internal/models"
"wm-backend/internal/models/requests"
"wm-backend/internal/models/responses"
"wm-backend/internal/repositories"
"wm-backend/pkg/helper"
"wm-backend/response"
"github.com/gin-gonic/gin"
"github.com/rs/zerolog/log"
)
// AlternativeComponentCreate creates a new alternative component.
//
// @Summary Create a new alternative component
// @Description Create a new alternative component with the provided details
// @Tags alternative-component
// @Accept json
// @Produce json
// @Param body body requests.CreateAlternativeComponentRequest true "Alternative component request body"
// @Success 201 {object} response.SuccessResponse{data=responses.CreateAlternativeComponentResponse}
// @Failure 400 {object} response.ErrorResponse
// @Failure 500 {object} response.ErrorResponse
// @Router /v1/alternative-components [post]
func AlternativeComponentCreate(c *gin.Context) error {
requestBody := requests.CreateAlternativeComponentRequest{}
if helper.IsShouldBindJSON(c, &requestBody) {
return nil
}
entityModel := &models.AlternativeComponent{
InvoiceConfigItemID: requestBody.InvoiceConfigItemID,
AlternativeComponentID: requestBody.AlternativeComponentID,
ConversionRatio: requestBody.ConversionRatio,
Priority: requestBody.Priority,
Note: requestBody.Note,
}
entity, err := repositories.CreateAlternativeComponent(c.Request.Context(), global.Queries, *entityModel)
if err != nil {
log.Error().Err(err).Msg("Failed to create alternative component")
response.InternalServerError(c, http.StatusInternalServerError, "Failed to create alternative component")
return nil
}
response.Created(c, "Alternative component created successfully", &responses.CreateAlternativeComponentResponse{
ID: entity.ID,
})
return nil
}
// AlternativeComponentGetByID retrieves a single alternative component by its ID.
//
// @Summary Get alternative component by ID
// @Description Retrieve a single alternative component using its unique identifier
// @Tags alternative-component
// @Accept json
// @Produce json
// @Param id path int true "Alternative component ID"
// @Success 200 {object} response.SuccessResponse{data=models.AlternativeComponent}
// @Failure 400 {object} response.ErrorResponse
// @Failure 404 {object} response.ErrorResponse
// @Failure 500 {object} response.ErrorResponse
// @Router /v1/alternative-components/{id} [get]
func AlternativeComponentGetByID(c *gin.Context) error {
id, err := strconv.ParseInt(c.Param("id"), 10, 64)
if err != nil {
response.BadRequestError(c, http.StatusBadRequest, "Invalid ID")
return nil
}
entity, err := repositories.GetAlternativeComponentByID(c.Request.Context(), global.Queries, id)
if err != nil {
log.Error().Err(err).Msgf("Failed to get alternative component by ID: %d", id)
response.NotFoundError(c, http.StatusNotFound, "Alternative component not found")
return nil
}
response.Ok(c, "Success", entity)
return nil
}
// AlternativeComponentList retrieves all alternative components.
//
// @Summary List all alternative components
// @Description Retrieve a list of all alternative components
// @Tags alternative-component
// @Accept json
// @Produce json
// @Success 200 {object} response.SuccessResponse{data=[]models.AlternativeComponent}
// @Failure 500 {object} response.ErrorResponse
// @Router /v1/alternative-components [get]
func AlternativeComponentList(c *gin.Context) error {
entities, err := repositories.ListAlternativeComponents(c.Request.Context(), global.Queries)
if err != nil {
response.InternalServerError(c, http.StatusInternalServerError, "Failed to list alternative components")
return nil
}
response.Ok(c, "Success", entities)
return nil
}
// AlternativeComponentUpdate updates an existing alternative component by its ID.
//
// @Summary Update alternative component
// @Description Update an existing alternative component by its ID. Only non-empty fields will be updated.
// @Tags alternative-component
// @Accept json
// @Produce json
// @Param id path int true "Alternative component ID"
// @Param body body requests.UpdateAlternativeComponentRequest true "Alternative component request body"
// @Success 200 {object} response.SuccessResponse{data=responses.UpdateAlternativeComponentResponse}
// @Failure 400 {object} response.ErrorResponse
// @Failure 404 {object} response.ErrorResponse
// @Failure 500 {object} response.ErrorResponse
// @Router /v1/alternative-components/{id} [put]
func AlternativeComponentUpdate(c *gin.Context) error {
id, err := strconv.ParseInt(c.Param("id"), 10, 64)
if err != nil {
response.BadRequestError(c, http.StatusBadRequest, "Invalid ID")
return nil
}
requestBody := requests.UpdateAlternativeComponentRequest{}
if helper.IsShouldBindJSON(c, &requestBody) {
return nil
}
existing, err := repositories.GetAlternativeComponentByID(c.Request.Context(), global.Queries, id)
if err != nil {
response.NotFoundError(c, http.StatusNotFound, "Alternative component not found")
return nil
}
if requestBody.InvoiceConfigItemID != nil {
existing.InvoiceConfigItemID = *requestBody.InvoiceConfigItemID
}
if requestBody.AlternativeComponentID != nil {
existing.AlternativeComponentID = *requestBody.AlternativeComponentID
}
if requestBody.ConversionRatio != nil {
existing.ConversionRatio = *requestBody.ConversionRatio
}
if requestBody.Priority != nil {
existing.Priority = *requestBody.Priority
}
if requestBody.Note != "" {
existing.Note = requestBody.Note
}
entity, err := repositories.UpdateAlternativeComponent(c.Request.Context(), global.Queries, existing)
if err != nil {
log.Error().Err(err).Msgf("Failed to update alternative component with ID: %d", id)
response.InternalServerError(c, http.StatusInternalServerError, "Failed to update alternative component")
return nil
}
response.Ok(c, "Alternative component updated successfully", &responses.UpdateAlternativeComponentResponse{
ID: entity.ID,
InvoiceConfigItemID: entity.InvoiceConfigItemID,
AlternativeComponentID: entity.AlternativeComponentID,
ConversionRatio: entity.ConversionRatio,
Priority: entity.Priority,
Note: entity.Note,
})
return nil
}
// AlternativeComponentDelete deletes an alternative component by its ID.
//
// @Summary Delete alternative component
// @Description Delete an alternative component by its unique identifier
// @Tags alternative-component
// @Accept json
// @Produce json
// @Param id path int true "Alternative component ID"
// @Success 200 {object} response.SuccessResponse
// @Failure 400 {object} response.ErrorResponse
// @Failure 500 {object} response.ErrorResponse
// @Router /v1/alternative-components/{id} [delete]
func AlternativeComponentDelete(c *gin.Context) error {
id, err := strconv.ParseInt(c.Param("id"), 10, 64)
if err != nil {
response.BadRequestError(c, http.StatusBadRequest, "Invalid ID")
return nil
}
rowsAffected, err := repositories.DeleteAlternativeComponent(c.Request.Context(), global.Queries, id)
if err != nil {
log.Error().Err(err).Msgf("Failed to delete alternative component with ID: %d", id)
response.InternalServerError(c, http.StatusInternalServerError, "Failed to delete alternative component")
return nil
}
if rowsAffected == 0 {
response.NotFoundError(c, http.StatusNotFound, "Alternative component not found")
return nil
}
response.Ok(c, "Delete Success", nil)
return nil
}

View File

@@ -0,0 +1,201 @@
package services
import (
"net/http"
"strconv"
"time"
"wm-backend/global"
"wm-backend/internal/models"
"wm-backend/internal/models/requests"
"wm-backend/internal/models/responses"
"wm-backend/internal/repositories"
"wm-backend/pkg/helper"
"wm-backend/response"
"github.com/gin-gonic/gin"
"github.com/rs/zerolog/log"
)
// InvoiceCreate creates a new invoice.
//
// @Summary Create a new invoice
// @Description Create a new invoice with the provided details
// @Tags invoice
// @Accept json
// @Produce json
// @Param body body requests.CreateInvoiceRequest true "Invoice request body"
// @Success 201 {object} response.SuccessResponse{data=responses.CreateInvoiceResponse}
// @Failure 400 {object} response.ErrorResponse
// @Failure 500 {object} response.ErrorResponse
// @Router /v1/invoices [post]
func InvoiceCreate(c *gin.Context) error {
requestBody := requests.CreateInvoiceRequest{}
if helper.IsShouldBindJSON(c, &requestBody) {
return nil
}
invoiceModel := &models.Invoice{
Type: requestBody.Type,
Status: requestBody.Status,
InvoiceConfigID: requestBody.InvoiceConfigID,
TotalItems: requestBody.TotalItems,
Note: requestBody.Note,
CreatedBy: requestBody.CreatedBy,
ApprovedBy: requestBody.ApprovedBy,
CreatedAt: time.Now(),
}
invoice, err := repositories.CreateInvoice(c.Request.Context(), global.Queries, *invoiceModel)
if err != nil {
log.Error().Err(err).Msg("Failed to create invoice")
response.InternalServerError(c, http.StatusInternalServerError, "Failed to create invoice")
return nil
}
response.Created(c, "Invoice created successfully", &responses.CreateInvoiceResponse{
ID: invoice.ID,
InvoiceCode: invoice.InvoiceCode,
})
return nil
}
// InvoiceGetByID retrieves a single invoice by its ID.
//
// @Summary Get invoice by ID
// @Description Retrieve a single invoice using its unique identifier
// @Tags invoice
// @Accept json
// @Produce json
// @Param id path int true "Invoice ID"
// @Success 200 {object} response.SuccessResponse{data=models.Invoice}
// @Failure 400 {object} response.ErrorResponse
// @Failure 404 {object} response.ErrorResponse
// @Failure 500 {object} response.ErrorResponse
// @Router /v1/invoices/{id} [get]
func InvoiceGetByID(c *gin.Context) error {
id, err := strconv.ParseInt(c.Param("id"), 10, 64)
if err != nil {
response.BadRequestError(c, http.StatusBadRequest, "Invalid ID")
return nil
}
invoice, err := repositories.GetInvoiceByID(c.Request.Context(), global.Queries, id)
if err != nil {
log.Error().Err(err).Msgf("Failed to get invoice by ID: %d", id)
response.NotFoundError(c, http.StatusNotFound, "Invoice not found")
return nil
}
response.Ok(c, "Success", invoice)
return nil
}
// InvoiceList retrieves all invoices.
//
// @Summary List all invoices
// @Description Retrieve a list of all invoices ordered by creation date
// @Tags invoice
// @Accept json
// @Produce json
// @Success 200 {object} response.SuccessResponse{data=[]models.Invoice}
// @Failure 500 {object} response.ErrorResponse
// @Router /v1/invoices [get]
func InvoiceList(c *gin.Context) error {
invoices, err := repositories.ListInvoices(c.Request.Context(), global.Queries)
if err != nil {
response.InternalServerError(c, http.StatusInternalServerError, "Failed to list invoices")
return nil
}
response.Ok(c, "Success", invoices)
return nil
}
// InvoiceUpdate updates an existing invoice by its ID.
//
// @Summary Update invoice
// @Description Update an existing invoice by its ID. Only non-empty fields will be updated.
// @Tags invoice
// @Accept json
// @Produce json
// @Param id path int true "Invoice ID"
// @Param body body requests.UpdateInvoiceRequest true "Invoice request body"
// @Success 200 {object} response.SuccessResponse{data=responses.UpdateInvoiceResponse}
// @Failure 400 {object} response.ErrorResponse
// @Failure 404 {object} response.ErrorResponse
// @Failure 500 {object} response.ErrorResponse
// @Router /v1/invoices/{id} [put]
func InvoiceUpdate(c *gin.Context) error {
id, err := strconv.ParseInt(c.Param("id"), 10, 64)
if err != nil {
response.BadRequestError(c, http.StatusBadRequest, "Invalid ID")
return nil
}
requestBody := requests.UpdateInvoiceRequest{}
if helper.IsShouldBindJSON(c, &requestBody) {
return nil
}
existing, err := repositories.GetInvoiceByID(c.Request.Context(), global.Queries, id)
if err != nil {
response.NotFoundError(c, http.StatusNotFound, "Invoice not found")
return nil
}
if requestBody.Type != nil {
existing.Type = *requestBody.Type
}
if requestBody.Status != nil {
existing.Status = *requestBody.Status
}
if requestBody.InvoiceConfigID != nil {
existing.InvoiceConfigID = *requestBody.InvoiceConfigID
}
if requestBody.TotalItems != nil {
existing.TotalItems = *requestBody.TotalItems
}
if requestBody.Note != "" {
existing.Note = requestBody.Note
}
existing.UpdatedAt = time.Now()
invoice, err := repositories.UpdateInvoice(c.Request.Context(), global.Queries, existing)
if err != nil {
log.Error().Err(err).Msgf("Failed to update invoice with ID: %d", id)
response.InternalServerError(c, http.StatusInternalServerError, "Failed to update invoice")
return nil
}
response.Ok(c, "Invoice updated successfully", &responses.UpdateInvoiceResponse{
ID: invoice.ID,
InvoiceCode: invoice.InvoiceCode,
Type: invoice.Type,
Status: invoice.Status,
InvoiceConfigID: invoice.InvoiceConfigID,
TotalItems: invoice.TotalItems,
Note: invoice.Note,
})
return nil
}
// InvoiceDelete deletes an invoice by its ID.
//
// @Summary Delete invoice
// @Description Delete an invoice by its unique identifier
// @Tags invoice
// @Accept json
// @Produce json
// @Param id path int true "Invoice ID"
// @Success 200 {object} response.SuccessResponse
// @Failure 400 {object} response.ErrorResponse
// @Failure 500 {object} response.ErrorResponse
// @Router /v1/invoices/{id} [delete]
func InvoiceDelete(c *gin.Context) error {
id, err := strconv.ParseInt(c.Param("id"), 10, 64)
if err != nil {
response.BadRequestError(c, http.StatusBadRequest, "Invalid ID")
return nil
}
rowsAffected, err := repositories.DeleteInvoice(c.Request.Context(), global.Queries, id)
if err != nil {
log.Error().Err(err).Msgf("Failed to delete invoice with ID: %d", id)
response.InternalServerError(c, http.StatusInternalServerError, "Failed to delete invoice")
return nil
}
if rowsAffected == 0 {
response.NotFoundError(c, http.StatusNotFound, "Invoice not found")
return nil
}
response.Ok(c, "Delete Success", nil)
return nil
}

View File

@@ -0,0 +1,166 @@
// Code generated by sqlc. DO NOT EDIT.
// versions:
// sqlc v1.30.0
// source: alternative_component.sql
package db
import (
"context"
"github.com/jackc/pgx/v5/pgtype"
)
const createAlternativeComponent = `-- name: CreateAlternativeComponent :one
INSERT INTO alternative_components (invoice_config_item_id, alternative_component_id, conversion_ratio, priority, note, metadata)
VALUES (
$1,
$2,
$3,
$4,
$5,
$6
)
RETURNING id, invoice_config_item_id, alternative_component_id, conversion_ratio, priority, note, metadata
`
type CreateAlternativeComponentParams struct {
InvoiceConfigItemID int64 `db:"invoice_config_item_id" json:"invoiceConfigItemId"`
AlternativeComponentID int64 `db:"alternative_component_id" json:"alternativeComponentId"`
ConversionRatio pgtype.Numeric `db:"conversion_ratio" json:"conversionRatio"`
Priority int32 `db:"priority" json:"priority"`
Note pgtype.Text `db:"note" json:"note"`
Metadata []byte `db:"metadata" json:"metadata"`
}
func (q *Queries) CreateAlternativeComponent(ctx context.Context, arg CreateAlternativeComponentParams) (AlternativeComponent, error) {
row := q.db.QueryRow(ctx, createAlternativeComponent,
arg.InvoiceConfigItemID,
arg.AlternativeComponentID,
arg.ConversionRatio,
arg.Priority,
arg.Note,
arg.Metadata,
)
var i AlternativeComponent
err := row.Scan(
&i.ID,
&i.InvoiceConfigItemID,
&i.AlternativeComponentID,
&i.ConversionRatio,
&i.Priority,
&i.Note,
&i.Metadata,
)
return i, err
}
const deleteAlternativeComponent = `-- name: DeleteAlternativeComponent :execrows
DELETE FROM alternative_components
WHERE id = $1
`
func (q *Queries) DeleteAlternativeComponent(ctx context.Context, id int64) (int64, error) {
result, err := q.db.Exec(ctx, deleteAlternativeComponent, id)
if err != nil {
return 0, err
}
return result.RowsAffected(), nil
}
const getAlternativeComponentByID = `-- name: GetAlternativeComponentByID :one
SELECT id, invoice_config_item_id, alternative_component_id, conversion_ratio, priority, note, metadata FROM alternative_components
WHERE id = $1
`
func (q *Queries) GetAlternativeComponentByID(ctx context.Context, id int64) (AlternativeComponent, error) {
row := q.db.QueryRow(ctx, getAlternativeComponentByID, id)
var i AlternativeComponent
err := row.Scan(
&i.ID,
&i.InvoiceConfigItemID,
&i.AlternativeComponentID,
&i.ConversionRatio,
&i.Priority,
&i.Note,
&i.Metadata,
)
return i, err
}
const listAlternativeComponents = `-- name: ListAlternativeComponents :many
SELECT id, invoice_config_item_id, alternative_component_id, conversion_ratio, priority, note, metadata FROM alternative_components
`
func (q *Queries) ListAlternativeComponents(ctx context.Context) ([]AlternativeComponent, error) {
rows, err := q.db.Query(ctx, listAlternativeComponents)
if err != nil {
return nil, err
}
defer rows.Close()
var items []AlternativeComponent
for rows.Next() {
var i AlternativeComponent
if err := rows.Scan(
&i.ID,
&i.InvoiceConfigItemID,
&i.AlternativeComponentID,
&i.ConversionRatio,
&i.Priority,
&i.Note,
&i.Metadata,
); err != nil {
return nil, err
}
items = append(items, i)
}
if err := rows.Err(); err != nil {
return nil, err
}
return items, nil
}
const updateAlternativeComponent = `-- name: UpdateAlternativeComponent :one
UPDATE alternative_components
SET invoice_config_item_id = coalesce($1, invoice_config_item_id),
alternative_component_id = coalesce($2, alternative_component_id),
conversion_ratio = coalesce($3, conversion_ratio),
priority = coalesce($4, priority),
note = coalesce($5, note),
metadata = coalesce($6, metadata)
WHERE id = $7
RETURNING id, invoice_config_item_id, alternative_component_id, conversion_ratio, priority, note, metadata
`
type UpdateAlternativeComponentParams struct {
InvoiceConfigItemID int64 `db:"invoice_config_item_id" json:"invoiceConfigItemId"`
AlternativeComponentID int64 `db:"alternative_component_id" json:"alternativeComponentId"`
ConversionRatio pgtype.Numeric `db:"conversion_ratio" json:"conversionRatio"`
Priority int32 `db:"priority" json:"priority"`
Note pgtype.Text `db:"note" json:"note"`
Metadata []byte `db:"metadata" json:"metadata"`
ID int64 `db:"id" json:"id"`
}
func (q *Queries) UpdateAlternativeComponent(ctx context.Context, arg UpdateAlternativeComponentParams) (AlternativeComponent, error) {
row := q.db.QueryRow(ctx, updateAlternativeComponent,
arg.InvoiceConfigItemID,
arg.AlternativeComponentID,
arg.ConversionRatio,
arg.Priority,
arg.Note,
arg.Metadata,
arg.ID,
)
var i AlternativeComponent
err := row.Scan(
&i.ID,
&i.InvoiceConfigItemID,
&i.AlternativeComponentID,
&i.ConversionRatio,
&i.Priority,
&i.Note,
&i.Metadata,
)
return i, err
}

204
sqlc_gen/invoice.sql.go Normal file
View File

@@ -0,0 +1,204 @@
// Code generated by sqlc. DO NOT EDIT.
// versions:
// sqlc v1.30.0
// source: invoice.sql
package db
import (
"context"
"time"
"github.com/jackc/pgx/v5/pgtype"
)
const createInvoice = `-- name: CreateInvoice :one
INSERT INTO invoices (type, status, invoice_config_id, total_items, note, created_by, approved_by, created_at, metadata)
VALUES (
$1,
$2,
$3,
$4,
$5,
$6,
$7,
$8,
$9
)
RETURNING id, invoice_code, type, status, invoice_config_id, total_items, note, created_by, approved_by, completed_at, created_at, updated_at, metadata
`
type CreateInvoiceParams struct {
Type InvoiceTypeEnum `db:"type" json:"type"`
Status InvoiceStatusEnum `db:"status" json:"status"`
InvoiceConfigID pgtype.Int8 `db:"invoice_config_id" json:"invoiceConfigId"`
TotalItems int32 `db:"total_items" json:"totalItems"`
Note pgtype.Text `db:"note" json:"note"`
CreatedBy pgtype.Text `db:"created_by" json:"createdBy"`
ApprovedBy pgtype.Text `db:"approved_by" json:"approvedBy"`
CreatedAt time.Time `db:"created_at" json:"createdAt"`
Metadata []byte `db:"metadata" json:"metadata"`
}
func (q *Queries) CreateInvoice(ctx context.Context, arg CreateInvoiceParams) (Invoice, error) {
row := q.db.QueryRow(ctx, createInvoice,
arg.Type,
arg.Status,
arg.InvoiceConfigID,
arg.TotalItems,
arg.Note,
arg.CreatedBy,
arg.ApprovedBy,
arg.CreatedAt,
arg.Metadata,
)
var i Invoice
err := row.Scan(
&i.ID,
&i.InvoiceCode,
&i.Type,
&i.Status,
&i.InvoiceConfigID,
&i.TotalItems,
&i.Note,
&i.CreatedBy,
&i.ApprovedBy,
&i.CompletedAt,
&i.CreatedAt,
&i.UpdatedAt,
&i.Metadata,
)
return i, err
}
const deleteInvoice = `-- name: DeleteInvoice :execrows
DELETE FROM invoices
WHERE id = $1
`
func (q *Queries) DeleteInvoice(ctx context.Context, id int64) (int64, error) {
result, err := q.db.Exec(ctx, deleteInvoice, id)
if err != nil {
return 0, err
}
return result.RowsAffected(), nil
}
const getInvoiceByID = `-- name: GetInvoiceByID :one
SELECT id, invoice_code, type, status, invoice_config_id, total_items, note, created_by, approved_by, completed_at, created_at, updated_at, metadata FROM invoices
WHERE id = $1
`
func (q *Queries) GetInvoiceByID(ctx context.Context, id int64) (Invoice, error) {
row := q.db.QueryRow(ctx, getInvoiceByID, id)
var i Invoice
err := row.Scan(
&i.ID,
&i.InvoiceCode,
&i.Type,
&i.Status,
&i.InvoiceConfigID,
&i.TotalItems,
&i.Note,
&i.CreatedBy,
&i.ApprovedBy,
&i.CompletedAt,
&i.CreatedAt,
&i.UpdatedAt,
&i.Metadata,
)
return i, err
}
const listInvoices = `-- name: ListInvoices :many
SELECT id, invoice_code, type, status, invoice_config_id, total_items, note, created_by, approved_by, completed_at, created_at, updated_at, metadata FROM invoices
ORDER BY created_at DESC
`
func (q *Queries) ListInvoices(ctx context.Context) ([]Invoice, error) {
rows, err := q.db.Query(ctx, listInvoices)
if err != nil {
return nil, err
}
defer rows.Close()
var items []Invoice
for rows.Next() {
var i Invoice
if err := rows.Scan(
&i.ID,
&i.InvoiceCode,
&i.Type,
&i.Status,
&i.InvoiceConfigID,
&i.TotalItems,
&i.Note,
&i.CreatedBy,
&i.ApprovedBy,
&i.CompletedAt,
&i.CreatedAt,
&i.UpdatedAt,
&i.Metadata,
); err != nil {
return nil, err
}
items = append(items, i)
}
if err := rows.Err(); err != nil {
return nil, err
}
return items, nil
}
const updateInvoice = `-- name: UpdateInvoice :one
UPDATE invoices
SET type = coalesce($1, type),
status = coalesce($2, status),
invoice_config_id = coalesce($3, invoice_config_id),
total_items = coalesce($4, total_items),
note = coalesce($5, note),
metadata = coalesce($6, metadata),
updated_at = $7
WHERE id = $8
RETURNING id, invoice_code, type, status, invoice_config_id, total_items, note, created_by, approved_by, completed_at, created_at, updated_at, metadata
`
type UpdateInvoiceParams struct {
Type InvoiceTypeEnum `db:"type" json:"type"`
Status InvoiceStatusEnum `db:"status" json:"status"`
InvoiceConfigID pgtype.Int8 `db:"invoice_config_id" json:"invoiceConfigId"`
TotalItems int32 `db:"total_items" json:"totalItems"`
Note pgtype.Text `db:"note" json:"note"`
Metadata []byte `db:"metadata" json:"metadata"`
UpdatedAt time.Time `db:"updated_at" json:"updatedAt"`
ID int64 `db:"id" json:"id"`
}
func (q *Queries) UpdateInvoice(ctx context.Context, arg UpdateInvoiceParams) (Invoice, error) {
row := q.db.QueryRow(ctx, updateInvoice,
arg.Type,
arg.Status,
arg.InvoiceConfigID,
arg.TotalItems,
arg.Note,
arg.Metadata,
arg.UpdatedAt,
arg.ID,
)
var i Invoice
err := row.Scan(
&i.ID,
&i.InvoiceCode,
&i.Type,
&i.Status,
&i.InvoiceConfigID,
&i.TotalItems,
&i.Note,
&i.CreatedBy,
&i.ApprovedBy,
&i.CompletedAt,
&i.CreatedAt,
&i.UpdatedAt,
&i.Metadata,
)
return i, err
}

View File

@@ -13,6 +13,7 @@ import (
type Querier interface { type Querier interface {
AssignRoleToUser(ctx context.Context, arg AssignRoleToUserParams) (UserRole, error) AssignRoleToUser(ctx context.Context, arg AssignRoleToUserParams) (UserRole, error)
CountUsersByRoleID(ctx context.Context, roleID uuid.UUID) (int64, error) CountUsersByRoleID(ctx context.Context, roleID uuid.UUID) (int64, error)
CreateAlternativeComponent(ctx context.Context, arg CreateAlternativeComponentParams) (AlternativeComponent, error)
CreateCabinet(ctx context.Context, arg CreateCabinetParams) (Cabinet, error) CreateCabinet(ctx context.Context, arg CreateCabinetParams) (Cabinet, error)
CreateComponent(ctx context.Context, arg CreateComponentParams) (Component, error) CreateComponent(ctx context.Context, arg CreateComponentParams) (Component, error)
CreateComponentCode(ctx context.Context, arg CreateComponentCodeParams) (ComponentCode, error) CreateComponentCode(ctx context.Context, arg CreateComponentCodeParams) (ComponentCode, error)
@@ -20,6 +21,7 @@ type Querier interface {
CreateComponentStatusHistory(ctx context.Context, arg CreateComponentStatusHistoryParams) (ComponentStatusHistory, error) CreateComponentStatusHistory(ctx context.Context, arg CreateComponentStatusHistoryParams) (ComponentStatusHistory, error)
CreateComponentType(ctx context.Context, arg CreateComponentTypeParams) (ComponentType, error) CreateComponentType(ctx context.Context, arg CreateComponentTypeParams) (ComponentType, error)
CreateContainer(ctx context.Context, arg CreateContainerParams) (Container, error) CreateContainer(ctx context.Context, arg CreateContainerParams) (Container, error)
CreateInvoice(ctx context.Context, arg CreateInvoiceParams) (Invoice, error)
CreateInvoiceConfig(ctx context.Context, arg CreateInvoiceConfigParams) (InvoiceConfig, error) CreateInvoiceConfig(ctx context.Context, arg CreateInvoiceConfigParams) (InvoiceConfig, error)
CreateInvoiceConfigItem(ctx context.Context, arg CreateInvoiceConfigItemParams) (InvoiceConfigItem, error) CreateInvoiceConfigItem(ctx context.Context, arg CreateInvoiceConfigItemParams) (InvoiceConfigItem, error)
CreateRole(ctx context.Context, arg CreateRoleParams) (Role, error) CreateRole(ctx context.Context, arg CreateRoleParams) (Role, error)
@@ -27,12 +29,14 @@ type Querier interface {
CreateShelve(ctx context.Context, arg CreateShelveParams) (Shelf, error) CreateShelve(ctx context.Context, arg CreateShelveParams) (Shelf, error)
CreateUser(ctx context.Context, arg CreateUserParams) (uuid.UUID, error) CreateUser(ctx context.Context, arg CreateUserParams) (uuid.UUID, error)
CreateWarehouse(ctx context.Context, arg CreateWarehouseParams) (Warehouse, error) CreateWarehouse(ctx context.Context, arg CreateWarehouseParams) (Warehouse, error)
DeleteAlternativeComponent(ctx context.Context, id int64) (int64, error)
DeleteCabinet(ctx context.Context, id int64) (int64, error) DeleteCabinet(ctx context.Context, id int64) (int64, error)
DeleteComponent(ctx context.Context, id int64) (int64, error) DeleteComponent(ctx context.Context, id int64) (int64, error)
DeleteComponentCode(ctx context.Context, id int64) (int64, error) DeleteComponentCode(ctx context.Context, id int64) (int64, error)
DeleteComponentItem(ctx context.Context, id int64) (int64, error) DeleteComponentItem(ctx context.Context, id int64) (int64, error)
DeleteComponentType(ctx context.Context, id int64) (int64, error) DeleteComponentType(ctx context.Context, id int64) (int64, error)
DeleteContainer(ctx context.Context, id int64) (int64, error) DeleteContainer(ctx context.Context, id int64) (int64, error)
DeleteInvoice(ctx context.Context, id int64) (int64, error)
DeleteInvoiceConfig(ctx context.Context, id int64) (int64, error) DeleteInvoiceConfig(ctx context.Context, id int64) (int64, error)
DeleteInvoiceConfigItem(ctx context.Context, id int64) (int64, error) DeleteInvoiceConfigItem(ctx context.Context, id int64) (int64, error)
DeleteRole(ctx context.Context, id uuid.UUID) (int64, error) DeleteRole(ctx context.Context, id uuid.UUID) (int64, error)
@@ -40,6 +44,7 @@ type Querier interface {
DeleteShelve(ctx context.Context, id int64) (int64, error) DeleteShelve(ctx context.Context, id int64) (int64, error)
DeleteWarehouse(ctx context.Context, id int64) (int64, error) DeleteWarehouse(ctx context.Context, id int64) (int64, error)
FindComponentItem(ctx context.Context, componentid int64) ([]FindComponentItemRow, error) FindComponentItem(ctx context.Context, componentid int64) ([]FindComponentItemRow, error)
GetAlternativeComponentByID(ctx context.Context, id int64) (AlternativeComponent, error)
GetCabinetByID(ctx context.Context, id int64) (Cabinet, error) GetCabinetByID(ctx context.Context, id int64) (Cabinet, error)
GetComponentByID(ctx context.Context, id int64) (Component, error) GetComponentByID(ctx context.Context, id int64) (Component, error)
GetComponentCodeByID(ctx context.Context, id int64) (ComponentCode, error) GetComponentCodeByID(ctx context.Context, id int64) (ComponentCode, error)
@@ -47,6 +52,7 @@ type Querier interface {
GetComponentItemByID(ctx context.Context, id int64) (ComponentItem, error) GetComponentItemByID(ctx context.Context, id int64) (ComponentItem, error)
GetComponentTypeByID(ctx context.Context, id int64) (ComponentType, error) GetComponentTypeByID(ctx context.Context, id int64) (ComponentType, error)
GetContainerByID(ctx context.Context, id int64) (Container, error) GetContainerByID(ctx context.Context, id int64) (Container, error)
GetInvoiceByID(ctx context.Context, id int64) (Invoice, error)
GetInvoiceConfigByID(ctx context.Context, id int64) (InvoiceConfig, error) GetInvoiceConfigByID(ctx context.Context, id int64) (InvoiceConfig, error)
GetInvoiceConfigItemByID(ctx context.Context, id int64) (InvoiceConfigItem, error) GetInvoiceConfigItemByID(ctx context.Context, id int64) (InvoiceConfigItem, error)
GetRoleByID(ctx context.Context, id uuid.UUID) (Role, error) GetRoleByID(ctx context.Context, id uuid.UUID) (Role, error)
@@ -59,6 +65,7 @@ type Querier interface {
GetUserRolesByRoleID(ctx context.Context, roleID uuid.UUID) ([]GetUserRolesByRoleIDRow, error) GetUserRolesByRoleID(ctx context.Context, roleID uuid.UUID) ([]GetUserRolesByRoleIDRow, error)
GetUserRolesByUserID(ctx context.Context, userID uuid.UUID) ([]GetUserRolesByUserIDRow, error) GetUserRolesByUserID(ctx context.Context, userID uuid.UUID) ([]GetUserRolesByUserIDRow, error)
GetWarehouseByID(ctx context.Context, id int64) (Warehouse, error) GetWarehouseByID(ctx context.Context, id int64) (Warehouse, error)
ListAlternativeComponents(ctx context.Context) ([]AlternativeComponent, error)
ListCabinets(ctx context.Context) ([]Cabinet, error) ListCabinets(ctx context.Context) ([]Cabinet, error)
ListComponentCodes(ctx context.Context) ([]ComponentCode, error) ListComponentCodes(ctx context.Context) ([]ComponentCode, error)
ListComponentItems(ctx context.Context) ([]ComponentItem, error) ListComponentItems(ctx context.Context) ([]ComponentItem, error)
@@ -67,12 +74,14 @@ type Querier interface {
ListContainers(ctx context.Context) ([]Container, error) ListContainers(ctx context.Context) ([]Container, error)
ListInvoiceConfigItems(ctx context.Context) ([]InvoiceConfigItem, error) ListInvoiceConfigItems(ctx context.Context) ([]InvoiceConfigItem, error)
ListInvoiceConfigs(ctx context.Context) ([]InvoiceConfig, error) ListInvoiceConfigs(ctx context.Context) ([]InvoiceConfig, error)
ListInvoices(ctx context.Context) ([]Invoice, error)
ListRoles(ctx context.Context) ([]Role, error) ListRoles(ctx context.Context) ([]Role, error)
ListRooms(ctx context.Context) ([]Room, error) ListRooms(ctx context.Context) ([]Room, error)
ListShelves(ctx context.Context) ([]Shelf, error) ListShelves(ctx context.Context) ([]Shelf, error)
ListWarehouses(ctx context.Context) ([]Warehouse, error) ListWarehouses(ctx context.Context) ([]Warehouse, error)
RemoveAllRolesFromUser(ctx context.Context, userID uuid.UUID) error RemoveAllRolesFromUser(ctx context.Context, userID uuid.UUID) error
RemoveRoleFromUser(ctx context.Context, arg RemoveRoleFromUserParams) error RemoveRoleFromUser(ctx context.Context, arg RemoveRoleFromUserParams) error
UpdateAlternativeComponent(ctx context.Context, arg UpdateAlternativeComponentParams) (AlternativeComponent, error)
UpdateCabinet(ctx context.Context, arg UpdateCabinetParams) (Cabinet, error) UpdateCabinet(ctx context.Context, arg UpdateCabinetParams) (Cabinet, error)
UpdateComponent(ctx context.Context, arg UpdateComponentParams) (Component, error) UpdateComponent(ctx context.Context, arg UpdateComponentParams) (Component, error)
UpdateComponentCode(ctx context.Context, arg UpdateComponentCodeParams) (ComponentCode, error) UpdateComponentCode(ctx context.Context, arg UpdateComponentCodeParams) (ComponentCode, error)
@@ -81,6 +90,7 @@ type Querier interface {
UpdateComponentItemStatus(ctx context.Context, arg UpdateComponentItemStatusParams) (ComponentItem, error) UpdateComponentItemStatus(ctx context.Context, arg UpdateComponentItemStatusParams) (ComponentItem, error)
UpdateComponentType(ctx context.Context, arg UpdateComponentTypeParams) (ComponentType, error) UpdateComponentType(ctx context.Context, arg UpdateComponentTypeParams) (ComponentType, error)
UpdateContainer(ctx context.Context, arg UpdateContainerParams) (Container, error) UpdateContainer(ctx context.Context, arg UpdateContainerParams) (Container, error)
UpdateInvoice(ctx context.Context, arg UpdateInvoiceParams) (Invoice, error)
UpdateInvoiceConfig(ctx context.Context, arg UpdateInvoiceConfigParams) (InvoiceConfig, error) UpdateInvoiceConfig(ctx context.Context, arg UpdateInvoiceConfigParams) (InvoiceConfig, error)
UpdateInvoiceConfigItem(ctx context.Context, arg UpdateInvoiceConfigItemParams) (InvoiceConfigItem, error) UpdateInvoiceConfigItem(ctx context.Context, arg UpdateInvoiceConfigItemParams) (InvoiceConfigItem, error)
UpdateRole(ctx context.Context, arg UpdateRoleParams) (Role, error) UpdateRole(ctx context.Context, arg UpdateRoleParams) (Role, error)