Merge branch 'create-contract' into 'main'

Added create contact ednpoint

See merge request ukacorp/mesari/backend!16
This commit was merged in pull request #16.
This commit is contained in:
2023-10-10 06:39:06 +00:00
15 changed files with 1278 additions and 146 deletions

File diff suppressed because one or more lines are too long

View File

@@ -1,20 +1,23 @@
package controllers package controllers
import ( import (
"log"
"net/http" "net/http"
"strconv" "strconv"
"strings"
"time" "time"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
"gitlab.com/pactual1/backend/database/contract" "gitlab.com/pactual1/backend/database/contract"
"gitlab.com/pactual1/backend/models" "gitlab.com/pactual1/backend/models"
"gitlab.com/pactual1/backend/shared"
) )
func GetLatestContracts(c *gin.Context) { func GetLatestContracts(c *gin.Context) {
// Existing parameters // Existing parameters
limitStr := c.DefaultQuery("limit", "50") limitStr := c.DefaultQuery("limit", "50")
offsetStr := c.DefaultQuery("offset", "0") offsetStr := c.DefaultQuery("offset", "0")
status := c.DefaultQuery("status", models.ContractStatusActive) status := strings.Split(c.DefaultQuery("status", models.ContractStatusActive), ",")
// New/Updated optional parameters // New/Updated optional parameters
companyName := c.Query("company_name") companyName := c.Query("company_name")
@@ -81,7 +84,7 @@ func GetLatestContracts(c *gin.Context) {
} }
// Respond with the contracts and the total count // Respond with the contracts and the total count
c.JSON(http.StatusOK, gin.H{"total": total, "data": contracts}) c.JSON(http.StatusOK, gin.H{"total": total, "data": models.ConvertContractToResponse(contracts)})
} }
@@ -89,7 +92,7 @@ func GetBuyerContracts(c *gin.Context) {
// Existing parameters // Existing parameters
limitStr := c.DefaultQuery("limit", "50") limitStr := c.DefaultQuery("limit", "50")
offsetStr := c.DefaultQuery("offset", "0") offsetStr := c.DefaultQuery("offset", "0")
status := c.Query("status") status := strings.Split(c.DefaultQuery("status", models.ContractStatusActive), ",")
contractIDStr := c.DefaultQuery("contract_id","0") contractIDStr := c.DefaultQuery("contract_id","0")
dateCreatedStr := c.Query("date_created") dateCreatedStr := c.Query("date_created")
@@ -137,44 +140,51 @@ func GetBuyerContracts(c *gin.Context) {
} }
// Respond with the contracts and the total count // Respond with the contracts and the total count
c.JSON(http.StatusOK, gin.H{"total": total, "data": convertContractToResponseModel(contracts)}) c.JSON(http.StatusOK, gin.H{"total": total, "data": models.ConvertContractToResponseModel(contracts)})
} }
func GetContractStatuses(c *gin.Context) { func GetContractStatuses(c *gin.Context) {
// Respond with the contract statuses // Respond with the contract statuses
c.JSON(http.StatusOK, gin.H{"statuses": models.GetContractStatuses()}) c.JSON(http.StatusOK, gin.H{"data": models.GetContractStatuses()})
}
func convertContractToResponseModel(contracts []models.Contract) []models.ListContractResponse {
var listInvoiceResponses []models.ListContractResponse
// Get all statuses
statuses := models.GetContractStatuses()
statusMap := make(map[string]models.Status)
for _, s := range statuses {
statusMap[s.Value] = s
}
for _, contract := range contracts {
// Get the status based on Value in the DB
status, ok := statusMap[contract.Status]
if !ok {
status = models.Status{Key: "Unknown", Value: "unknown"}
}
listInvoiceResponse := models.ListContractResponse{
Status: models.KeyValue{Key: status.Key, Value: status.Value},
Buyer: models.CompanyShortResponse{ID: int(contract.BuyerID), Name: contract.BuyerName},
ContractID: int(contract.ID),
DateCreated: contract.CreatedAt,
NumberOfDevices: contract.NumberOfDevices,
}
listInvoiceResponses = append(listInvoiceResponses, listInvoiceResponse)
}
return listInvoiceResponses
} }
func CreateContract(c *gin.Context) {
var payload models.CreateContractRequestPayload
if err := c.ShouldBindJSON(&payload); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid JSON payload"})
log.Printf("Invalid JSON payload: %v", err)
return
}
db := shared.GetDb()
newContract := models.Contract{
BuyerID: payload.BuyerID,
SellerID: payload.SellerID,
Description: payload.Description,
ProductID: payload.ProductID,
MinTemp: payload.MinTemp,
MaxTemp: payload.MaxTemp,
ArrivalDate: time.Unix(payload.ArrivalDate, 0),
PenaltyType: payload.PenaltyRec,
PenaltyValue : payload.PenaltyValue,
PenaltyRec : payload.PenaltyRec,
}
if err := db.Create(&newContract).Error; err != nil {
log.Printf("SaveContractInfo CREATE - Contract DB Error: %v", err)
c.JSON(http.StatusInternalServerError, gin.H{"error": "Could not create new contract"})
return
}
log.Printf("Successfully received and saved contract: %v", newContract)
c.JSON(http.StatusOK, gin.H{"message": "Successfully received and saved contract", "id": newContract.ID})
}

View File

@@ -161,5 +161,5 @@ func GetDevicesByContract(c *gin.Context) {
return return
} }
// Respond with the devices // Respond with the devices
c.JSON(http.StatusOK,gin.H{"data" : devices}) c.JSON(http.StatusOK,gin.H{"data" : models.ConvertDeviceToResponse(devices)})
} }

View File

@@ -53,8 +53,10 @@ func GetInvoiceByID(c *gin.Context) {
return return
} }
invoiceResponses := models.ConvertInvoiceToResponse(invoices)
if len(invoices) > 0 { if len(invoices) > 0 {
c.JSON(http.StatusOK, gin.H{"data": invoices[0]}) c.JSON(http.StatusOK, gin.H{"data": invoiceResponses[0]})
} else { } else {
c.JSON(http.StatusNotFound, gin.H{"error": "Invoice not found"}) c.JSON(http.StatusNotFound, gin.H{"error": "Invoice not found"})
} }

View File

@@ -13,7 +13,7 @@ import (
) )
func GetContracts(status string, companyName string, companyAddress string, func GetContracts(status []string, companyName string, companyAddress string,
companyEmail string, companyPhone string, startTime *time.Time, endTime *time.Time, companyEmail string, companyPhone string, startTime *time.Time, endTime *time.Time,
contractName string, deviceIDs []int64, contractID int, dateCreated *time.Time, limit, offset int) ([]models.Contract, int64, int, error) { contractName string, deviceIDs []int64, contractID int, dateCreated *time.Time, limit, offset int) ([]models.Contract, int64, int, error) {
@@ -24,10 +24,10 @@ func GetContracts(status string, companyName string, companyAddress string,
// Define custom fields to be selected, varies based on joined tables // Define custom fields to be selected, varies based on joined tables
customFields := "contracts.*, array_length(contracts.device_ids, 1) as number_of_devices" customFields := "contracts.*, array_length(contracts.device_ids, 1) as number_of_devices"
// Search by Status // Search by Statuses
if status != "" { if len(status) > 0 {
db = db.Where("contracts.status = ?", status) db = db.Where("contracts.status IN (?)", status)
countDb = countDb.Where("contracts.status = ?", status) countDb = countDb.Where("contracts.status IN (?)", status)
} }
// Search by Company Fields // Search by Company Fields

View File

@@ -79,13 +79,14 @@ func GetDeviceInfoForContract (deviceID uint64, contract models.Contract) (model
} }
} }
deviceInfosResponse := models.ConvertDeviceInfoToResponse(deviceInfos)
// Loop through each deviceInfo to create GeoJSON features // Loop through each deviceInfo to create GeoJSON features
for _, info := range deviceInfos { for _, info := range deviceInfosResponse {
info.RawJSON = "" info.RawJSON = ""
feature := models.GeoJSONFeature{ feature := models.GeoJSONFeature{
Type: "Feature", Type: "Feature",
DeviceInfo: &info, DeviceInfoResponse: &info,
Geometry: models.GeoJSONGeometry{ Geometry: models.GeoJSONGeometry{
Type: "Point", Type: "Point",
Coordinates: []float64{info.Lon, info.Lat}, Coordinates: []float64{info.Lon, info.Lat},

View File

@@ -47,13 +47,15 @@ func GetInvoices(buyerName string, sortBy string, limit int, offset int, id uint
Find(&invoices).Error; err != nil { Find(&invoices).Error; err != nil {
return nil, 0, err return nil, 0, err
} }
for i := range invoices { for i := range invoices {
var sum int64 var sum int64
for _, item := range invoices[i].InvoiceItem { if invoices[i].InvoiceItem != nil {
for _, item := range *invoices[i].InvoiceItem {
sum += item.PriceCents * item.Quantity sum += item.PriceCents * item.Quantity
} }
invoices[i].PriceCents = sum invoices[i].PriceCents = sum
}
} }
return invoices, total, nil return invoices, total, nil

View File

@@ -1,20 +1,29 @@
package models package models
import "github.com/jinzhu/gorm" import (
"time"
"github.com/jinzhu/gorm"
)
type BaseModel struct {
ID uint `json:"id" gorm:"primaryKey"`
CreatedAt time.Time `json:"createdAt" gorm:"autoCreateTime"`
UpdatedAt time.Time `json:"updatedAt" gorm:"autoUpdateTime"`
}
type Company struct { type Company struct {
gorm.Model gorm.Model
Name string Name string `json:"name"`
Address string Address string `json:"address"`
Email string Email string `json:"email"`
Phone string Phone string `json:"phone"`
Users []User Users []User `json:"users"`
Devices []Device Devices []Device `json:"devices"`
} }
type CompanyShortResponse struct { type CompanyShortResponse struct {
ID int ID int `json:"id"`
Name string Name string `json:"name"`
} }

View File

@@ -9,22 +9,127 @@ import (
type Contract struct { type Contract struct {
gorm.Model gorm.Model
Name string Name string `json:"name"`
DeviceIDs pq.Int64Array `gorm:"type:integer[]"` DeviceIDs pq.Int64Array `json:"deviceIds" gorm:"type:integer[]"`
BuyerID uint BuyerID uint `json:"buyerId"`
StartLat float64 SellerID uint `json:"sellerId"`
StartLon float64 Description string `json:"description"`
EndLat float64 StartLat float64 `json:"startLat"`
EndLon float64 StartLon float64 `json:"startLon"`
StartTime time.Time EndLat float64 `json:"endLat"`
EndTime time.Time EndLon float64 `json:"endLon"`
Status string StartTime time.Time `json:"startTime"`
BlockchainID string EndTime time.Time `json:"endTime"`
ContractInfos []ContractInfo Status string `json:"status"`
BuyerName string `gorm:"-"` BlockchainID string `json:"blockchainId"`
NumberOfDevices int `gorm:"-"` ContractInfos []ContractInfo `json:"contractInfos"`
ProductID uint `json:"productId"`
MaxTemp float64 `json:"maxTemp"`
MinTemp float64 `json:"minTemp"`
ArrivalDate time.Time `json:"arrivalDate"`
PenaltyType string `json:"penaltyType"`
PenaltyValue int `json:"penaltyValue"`
PenaltyRec string `json:"penaltyRec"`
BuyerName string `json:"buyerName" gorm:"-"`
NumberOfDevices int `json:"numberOfDevices" gorm:"-"`
} }
type ContractResponse struct {
BaseModel
Name string `json:"name"`
DeviceIDs pq.Int64Array `json:"deviceIds" gorm:"type:integer[]"`
BuyerID uint `json:"buyerId"`
SellerID uint `json:"sellerId"`
Description string `json:"description"`
StartLat float64 `json:"startLat"`
StartLon float64 `json:"startLon"`
EndLat float64 `json:"endLat"`
EndLon float64 `json:"endLon"`
StartTime time.Time `json:"startTime"`
EndTime time.Time `json:"endTime"`
Status string `json:"status"`
BlockchainID string `json:"blockchainId"`
ContractInfos []ContractInfo `json:"contractInfos"`
ProductID uint `json:"productId"`
MaxTemp float64 `json:"maxTemp"`
MinTemp float64 `json:"minTemp"`
ArrivalDate time.Time `json:"arrivalDate"`
PenaltyType string `json:"penaltyType"`
PenaltyValue int `json:"penaltyValue"`
PenaltyRec string `json:"penaltyRec"`
BuyerName string `json:"buyerName" gorm:"-"`
NumberOfDevices int `json:"numberOfDevices" gorm:"-"`
}
func ConvertContractToResponse(contracts []Contract) []ContractResponse {
var contractResponses []ContractResponse
for _, contract := range contracts {
contractResponse := ContractResponse{
BaseModel: BaseModel{
ID: contract.ID,
CreatedAt: contract.CreatedAt,
UpdatedAt: contract.UpdatedAt,
},
Name: contract.Name,
DeviceIDs: contract.DeviceIDs,
BuyerID: contract.BuyerID,
SellerID: contract.SellerID,
Description: contract.Description,
StartLat: contract.StartLat,
StartLon: contract.StartLon,
EndLat: contract.EndLat,
EndLon: contract.EndLon,
StartTime: contract.StartTime,
EndTime: contract.EndTime,
Status: contract.Status,
BlockchainID: contract.BlockchainID,
ContractInfos: contract.ContractInfos,
ProductID: contract.ProductID,
MaxTemp: contract.MaxTemp,
MinTemp: contract.MinTemp,
ArrivalDate: contract.ArrivalDate,
PenaltyType: contract.PenaltyType,
PenaltyValue: contract.PenaltyValue,
PenaltyRec: contract.PenaltyRec,
BuyerName: contract.BuyerName,
NumberOfDevices: contract.NumberOfDevices,
}
contractResponses = append(contractResponses, contractResponse)
}
return contractResponses
}
func ConvertContractToResponseModel(contracts []Contract) []ListContractResponse {
var listInvoiceResponses []ListContractResponse
// Get all statuses
statuses := GetContractStatuses()
statusMap := make(map[string]Status)
for _, s := range statuses {
statusMap[s.Value] = s
}
for _, contract := range contracts {
// Get the status based on Value in the DB
status, ok := statusMap[contract.Status]
if !ok {
status = Status{Key: "", Value: ""}
}
listInvoiceResponse := ListContractResponse{
Status: KeyValue{Key: status.Key, Value: status.Value},
Buyer: CompanyShortResponse{ID: int(contract.BuyerID), Name: contract.BuyerName},
ContractID: int(contract.ID),
DateCreated: contract.CreatedAt,
NumberOfDevices: contract.NumberOfDevices,
}
listInvoiceResponses = append(listInvoiceResponses, listInvoiceResponse)
}
return listInvoiceResponses
}
const ContractStatusActive = "active" const ContractStatusActive = "active"
const ContractStatusPending = "pending" const ContractStatusPending = "pending"
const ContractStatusDraft = "draft" const ContractStatusDraft = "draft"
@@ -34,6 +139,13 @@ const ContractStatusExecuted = "executed"
const ContractStatusRevoked = "revoked" const ContractStatusRevoked = "revoked"
const PenaltyTypeAmount = "amount"
const PenaltyTypePercentage = "percentage"
const PenaltyRecDaily = "daily"
const PenaltyRecMonthly = "monthly"
type Status struct { type Status struct {
Key string `json:"key"` Key string `json:"key"`
Value string `json:"value"` Value string `json:"value"`
@@ -41,25 +153,38 @@ type Status struct {
func GetContractStatuses() []Status { func GetContractStatuses() []Status {
return []Status{ return []Status{
{Key: "Active", Value: "active"}, {Value: "Active", Key: "active"},
{Key: "Pending signature", Value: "pending"}, {Value: "Pending signature", Key: "pending"},
{Key: "Draft", Value: "draft"}, {Value: "Draft", Key: "draft"},
{Key: "Signed", Value: "signed"}, {Value: "Signed", Key: "signed"},
{Key: "Ready for Activation", Value: "ready_for_activation"}, {Value: "Ready for Activation", Key: "ready_for_activation"},
{Key: "Executed", Value: "executed"}, {Value: "Executed", Key: "executed"},
{Key: "Revoked", Value: "revoked"}, {Value: "Revoked", Key: "revoked"},
} }
} }
type ListContractResponse struct { type ListContractResponse struct {
Status KeyValue `json:"Status"` Status KeyValue `json:"status"`
Buyer CompanyShortResponse `json:"Buyer"` Buyer CompanyShortResponse `json:"buyer"`
ContractID int ContractID int `json:"contractID"`
NumberOfDevices int NumberOfDevices int `json:"numberOfDevices"`
DateCreated time.Time DateCreated time.Time `json:"dateCreated"`
} }
type CreateContractRequestPayload struct {
SellerID uint `json:"sellerId" binding:"required"`
BuyerID uint `json:"buyerId" binding:"required"`
Description string `json:"description"`
ProductID uint `json:"productId"`
MinTemp float64 `json:"minTemp" binding:"required"`
MaxTemp float64 `json:"maxTemp" binding:"required"`
ArrivalDate int64 `json:"arrivalDate"`
PenaltyType string `json:"penaltyType"`
PenaltyValue int `json:"penaltyValue"`
PenaltyRec string `json:"penaltyRec"`
}
func (Contract) Update() (bool, error) { func (Contract) Update() (bool, error) {
return false, nil return false, nil
} }
@@ -69,3 +194,5 @@ func (Contract) Create() (bool, error) {
func (Contract) Delete() (bool, error) { func (Contract) Delete() (bool, error) {
return false, nil return false, nil
} }

View File

@@ -4,15 +4,54 @@ import (
"github.com/jinzhu/gorm" "github.com/jinzhu/gorm"
) )
type Device struct { type Device struct {
gorm.Model gorm.Model
DeviceID string `json:"deviceId"` DeviceID string `json:"deviceId"`
DeviceName string DeviceName string `json:"deviceName"`
IMEI string `json:"imei"` IMEI string `json:"imei"`
IMSI string `json:"imsi"` IMSI string `json:"imsi"`
DeviceConfiguration string `gorm:"type:json"` DeviceConfiguration string `json:"deviceConfiguration" gorm:"type:json"`
CompanyID uint CompanyID uint `json:"companyId"`
DeviceInfos []DeviceInfo DeviceInfos *[]DeviceInfo `json:"deviceInfos"`
}
type DeviceResponse struct {
BaseModel
DeviceID string `json:"deviceId"`
DeviceName string `json:"deviceName"`
IMEI string `json:"imei"`
IMSI string `json:"imsi"`
DeviceConfiguration string `json:"deviceConfiguration" gorm:"type:json"`
CompanyID uint `json:"companyId"`
DeviceInfos *[]DeviceInfo `json:"deviceInfos"`
}
func ConvertDeviceToResponse(devices []Device) []DeviceResponse {
var deviceResponses []DeviceResponse
for _, device := range devices {
if device.DeviceInfos == nil {
emptySlice := make([]DeviceInfo, 0)
device.DeviceInfos = &emptySlice
}
deviceResponse := DeviceResponse{
BaseModel: BaseModel{
ID: device.ID,
CreatedAt: device.CreatedAt,
UpdatedAt: device.UpdatedAt,
},
DeviceID: device.DeviceID,
DeviceName: device.DeviceName,
IMEI: device.IMEI,
IMSI: device.IMSI,
DeviceConfiguration: device.DeviceConfiguration,
CompanyID: device.CompanyID,
DeviceInfos: device.DeviceInfos,
}
deviceResponses = append(deviceResponses, deviceResponse)
}
return deviceResponses
} }
func (Device) Update() (bool, error) { func (Device) Update() (bool, error) {
@@ -30,3 +69,4 @@ func (d *Device) Delete(db *gorm.DB) (bool, error) {
return true, nil return true, nil
} }

View File

@@ -1,6 +1,8 @@
package models package models
import "github.com/jinzhu/gorm" import (
"github.com/jinzhu/gorm"
)
// Location holds latitude and longitude. // Location holds latitude and longitude.
type Location struct { type Location struct {
@@ -10,17 +12,15 @@ type Location struct {
// ImportantInfo holds fields that are important for quick access. // ImportantInfo holds fields that are important for quick access.
type SensorData struct { type SensorData struct {
IMEI string `json:"imei"` IMEI string `json:"imei"`
IMSI string `json:"imsi"` IMSI string `json:"imsi"`
Timestamp int64 `json:"timestamp"` Timestamp int64 `json:"timestamp"`
Lat float64 `json:"lat"` Lat float64 `json:"lat"`
Lon float64 `json:"lon"` Lon float64 `json:"lon"`
WifiLoc Location `json:"wifi_location"` WifiLoc Location `json:"wifiLocation"`
CellLoc Location `json:"cell_location"` CellLoc Location `json:"cellLocation"`
Temperature float64 `json:"temperature"` Temperature float64 `json:"temperature"`
// Used to parse incoming json data AccInfo AccelerometerInfo `json:"accelerometerInfo"`
AccInfo AccelerometerInfo `json:"accelerometerInfo"`
// Used to store coordinates of accelerometer to DB
AccelerometerInfo AccelerometerInfo
} }
@@ -33,12 +33,38 @@ type DeviceInfo struct {
} }
type AccelerometerInfo struct { type DeviceInfoResponse struct {
X int64 BaseModel
Y int64 RawJSON string `json:"rawJson" gorm:"type:json"`
Z int64 SensorData
DeviceID uint `json:"deviceId"`
ExternalDeviceID string `json:"externalDeviceId"`
} }
func ConvertDeviceInfoToResponse(deviceInfos []DeviceInfo) []DeviceInfoResponse {
var deviceInfoResponses []DeviceInfoResponse
for _, deviceInfo := range deviceInfos {
deviceInfoResponse := DeviceInfoResponse{
BaseModel: BaseModel{
ID: deviceInfo.ID,
CreatedAt: deviceInfo.CreatedAt,
UpdatedAt: deviceInfo.UpdatedAt,
},
RawJSON: deviceInfo.RawJSON,
SensorData: deviceInfo.SensorData,
DeviceID: deviceInfo.DeviceID,
ExternalDeviceID: deviceInfo.ExternalDeviceID,
}
deviceInfoResponses = append(deviceInfoResponses, deviceInfoResponse)
}
return deviceInfoResponses
}
type AccelerometerInfo struct {
X int64 `json:"x"`
Y int64 `json:"y"`
Z int64 `json:"z"`
}
type GeoJSONFeatureCollection struct { type GeoJSONFeatureCollection struct {
Type string `json:"type"` Type string `json:"type"`
Features []GeoJSONFeature `json:"features"` Features []GeoJSONFeature `json:"features"`
@@ -47,7 +73,7 @@ type GeoJSONFeatureCollection struct {
type GeoJSONFeature struct { type GeoJSONFeature struct {
Type string `json:"type"` Type string `json:"type"`
Geometry GeoJSONGeometry `json:"geometry"` Geometry GeoJSONGeometry `json:"geometry"`
DeviceInfo *DeviceInfo `json:",omitempty"` DeviceInfoResponse *DeviceInfoResponse `json:"deviceInfo,omitempty"`
Properties map[string]interface{} `json:"properties"` Properties map[string]interface{} `json:"properties"`
} }
@@ -56,7 +82,6 @@ type GeoJSONGeometry struct {
Coordinates []float64 `json:"coordinates"` Coordinates []float64 `json:"coordinates"`
} }
func (DeviceInfo) Update() (bool, error) { func (DeviceInfo) Update() (bool, error) {
return false, nil return false, nil
} }

View File

@@ -1,6 +1,7 @@
package models package models
import ( import (
"database/sql"
"time" "time"
"github.com/jinzhu/gorm" "github.com/jinzhu/gorm"
@@ -8,42 +9,113 @@ import (
type Invoice struct { type Invoice struct {
gorm.Model gorm.Model
BuyerID uint ID uint `json:"id" gorm:"primaryKey"`
BuyerName string CreatedAt time.Time `json:"createdAt"`
BuyerAddress string UpdatedAt time.Time `json:"updatedAt"`
BuyerEmail string DeletedAt sql.NullTime `json:"deletedAt" gorm:"index"`
BuyerPhone string BuyerID uint `json:"buyerId"`
SellerID uint BuyerName string `json:"buyerName"`
SellerName string BuyerAddress string `json:"buyerAddress"`
SellerAddress string BuyerEmail string `json:"buyerEmail"`
SellerEmail string BuyerPhone string `json:"buyerPhone"`
SellerPhone string SellerID uint `json:"sellerId"`
PriceCents int64 `gorm:"column:price_cents"` SellerName string `json:"sellerName"`
Discount int64 SellerAddress string `json:"sellerAddress"`
Tax int64 SellerEmail string `json:"sellerEmail"`
TermsAndConditions string SellerPhone string `json:"sellerPhone"`
InvoiceName string PriceCents int64 `json:"priceCents" gorm:"column:price_cents"`
InvoiceDate time.Time Discount int64 `json:"discount"`
InvoiceDueDate time.Time Tax int64 `json:"tax"`
ContractID uint TermsAndConditions string `json:"termsAndConditions"`
InvoiceItem [] InvoiceItem InvoiceName string `json:"invoiceName"`
Status string InvoiceDate time.Time `json:"invoiceDate"`
InvoiceDueDate time.Time `json:"invoiceDueDate"`
ContractID uint `json:"contractId"`
InvoiceItem *[]InvoiceItem `json:"invoiceItem"`
Status string `json:"status"`
} }
type InvoiceResponse struct {
BaseModel
ID uint `json:"id" gorm:"primaryKey"`
CreatedAt time.Time `json:"createdAt"`
UpdatedAt time.Time `json:"updatedAt"`
DeletedAt sql.NullTime `json:"deletedAt" gorm:"index"`
BuyerID uint `json:"buyerId"`
BuyerName string `json:"buyerName"`
BuyerAddress string `json:"buyerAddress"`
BuyerEmail string `json:"buyerEmail"`
BuyerPhone string `json:"buyerPhone"`
SellerID uint `json:"sellerId"`
SellerName string `json:"sellerName"`
SellerAddress string `json:"sellerAddress"`
SellerEmail string `json:"sellerEmail"`
SellerPhone string `json:"sellerPhone"`
PriceCents int64 `json:"priceCents" gorm:"column:price_cents"`
Discount int64 `json:"discount"`
Tax int64 `json:"tax"`
TermsAndConditions string `json:"termsAndConditions"`
InvoiceName string `json:"invoiceName"`
InvoiceDate time.Time `json:"invoiceDate"`
InvoiceDueDate time.Time `json:"invoiceDueDate"`
ContractID uint `json:"contractId"`
InvoiceItem *[]InvoiceItem `json:"invoiceItem"`
Status string `json:"status"`
}
func ConvertInvoiceToResponse(invoices []Invoice) []InvoiceResponse {
var invoiceResponses []InvoiceResponse
for _, invoice := range invoices {
if invoice.InvoiceItem == nil {
emptySlice := make([]InvoiceItem, 0)
invoice.InvoiceItem = &emptySlice
}
invoiceResponse := InvoiceResponse{
BaseModel: BaseModel{
ID: invoice.ID,
CreatedAt: invoice.CreatedAt,
UpdatedAt: invoice.UpdatedAt,
},
BuyerID: invoice.BuyerID,
BuyerName: invoice.BuyerName,
BuyerAddress: invoice.BuyerAddress,
BuyerEmail: invoice.BuyerEmail,
BuyerPhone: invoice.BuyerPhone,
SellerID: invoice.SellerID,
SellerName: invoice.SellerName,
SellerAddress: invoice.SellerAddress,
SellerEmail: invoice.SellerEmail,
SellerPhone: invoice.SellerPhone,
PriceCents: invoice.PriceCents,
Discount: invoice.Discount,
Tax: invoice.Tax,
TermsAndConditions: invoice.TermsAndConditions,
InvoiceName: invoice.InvoiceName,
InvoiceDate: invoice.InvoiceDate,
InvoiceDueDate: invoice.InvoiceDueDate,
ContractID: invoice.ContractID,
InvoiceItem: invoice.InvoiceItem,
Status: invoice.Status,
}
invoiceResponses = append(invoiceResponses, invoiceResponse)
}
return invoiceResponses
}
type ListInvoiceResponse struct { type ListInvoiceResponse struct {
Status KeyValue `json:"Status"` Status KeyValue `json:"status"`
Buyer CompanyShortResponse `json:"Buyer"` Buyer CompanyShortResponse `json:"buyer"`
ContractID int ContractID int `json:"contractId"`
DateCreated time.Time DateCreated time.Time `json:"dateCreated"`
DueDate time.Time DueDate time.Time `json:"dueDate"`
Amount string Amount string `json:"amount"`
} }
type KeyValue struct { type KeyValue struct {
Key string Key string `json:"key"`
Value string Value string `json:"value"`
} }

View File

@@ -1,18 +1,60 @@
package models package models
import ( import (
"database/sql"
"time"
"github.com/jinzhu/gorm" "github.com/jinzhu/gorm"
) )
type InvoiceItem struct { type InvoiceItem struct {
gorm.Model gorm.Model
Description string ID uint `json:"id" gorm:"primaryKey"`
Quantity int64 CreatedAt time.Time `json:"createdAt"`
Unit string UpdatedAt time.Time `json:"updatedAt"`
PriceCents int64 `gorm:"column:price_cents"` DeletedAt sql.NullTime `json:"deletedAt" gorm:"index"`
InvoiceID uint Description string `json:"description"`
Quantity int64 `json:"quantity"`
Unit string `json:"unit"`
PriceCents int64 `json:"priceCents" gorm:"column:price_cents"`
InvoiceID uint `json:"invoiceId"`
} }
type InvoiceItemResponse struct {
BaseModel
ID uint `json:"id" gorm:"primaryKey"`
CreatedAt time.Time `json:"createdAt"`
UpdatedAt time.Time `json:"updatedAt"`
DeletedAt sql.NullTime `json:"deletedAt" gorm:"index"`
Description string `json:"description"`
Quantity int64 `json:"quantity"`
Unit string `json:"unit"`
PriceCents int64 `json:"priceCents" gorm:"column:price_cents"`
InvoiceID uint `json:"invoiceId"`
}
// ConvertSliceOfInvoiceItemToResponse converts a slice of InvoiceItem models to a slice of InvoiceItemResponse models
func ConvertInvoiceItemToResponse(items []InvoiceItem) []InvoiceItemResponse {
var itemResponses []InvoiceItemResponse
for _, item := range items {
itemResponse := InvoiceItemResponse{
BaseModel: BaseModel{
ID: item.ID,
CreatedAt: item.CreatedAt,
UpdatedAt: item.UpdatedAt,
},
Description: item.Description,
Quantity: item.Quantity,
Unit: item.Unit,
PriceCents: item.PriceCents,
InvoiceID: item.InvoiceID,
}
itemResponses = append(itemResponses, itemResponse)
}
return itemResponses
}
func (InvoiceItem) Update() (bool, error) { func (InvoiceItem) Update() (bool, error) {

View File

@@ -1,14 +1,23 @@
package models package models
import "github.com/jinzhu/gorm" import (
"database/sql"
"time"
"github.com/jinzhu/gorm"
)
type User struct { type User struct {
gorm.Model gorm.Model
Username string ID uint `json:"id" gorm:"primaryKey"`
Password string CreatedAt time.Time `json:"createdAt"`
Email string UpdatedAt time.Time `json:"updatedAt"`
Avatar string DeletedAt sql.NullTime `json:"deletedAt" gorm:"index"`
CompanyID uint Username string `json:"username"`
Password string `json:"password"`
Email string `json:"email"`
Avatar string `json:"avatar"`
CompanyID uint `json:"companyId"`
} }
func (User) Update() (bool, error) { func (User) Update() (bool, error) {

View File

@@ -26,6 +26,7 @@ func RegisterPublicRoutes(r *gin.Engine) {
// Contracts // Contracts
r.GET("/contracts/statuses", controllers.GetContractStatuses) r.GET("/contracts/statuses", controllers.GetContractStatuses)
r.GET("/contracts/list", controllers.GetBuyerContracts) r.GET("/contracts", controllers.GetBuyerContracts)
r.POST("/contracts/create", controllers.CreateContract)
} }