forked from ebhomengo/niki
Merge branch 'develop' into feat/shopping-basket
This commit is contained in:
commit
7e202fffb9
|
|
@ -3,8 +3,8 @@ package main
|
||||||
import (
|
import (
|
||||||
"flag"
|
"flag"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
purchaseMysql "git.gocasts.ir/ebhomengo/niki/domain/purchase/repository/mysql"
|
||||||
"git.gocasts.ir/ebhomengo/niki/purchaseapp/delivery/http"
|
"git.gocasts.ir/ebhomengo/niki/purchaseapp/delivery/http"
|
||||||
purchaseMysql "git.gocasts.ir/ebhomengo/niki/purchaseapp/repository/mysql"
|
|
||||||
"git.gocasts.ir/ebhomengo/niki/purchaseapp/service/order"
|
"git.gocasts.ir/ebhomengo/niki/purchaseapp/service/order"
|
||||||
"git.gocasts.ir/ebhomengo/niki/repository/migrator"
|
"git.gocasts.ir/ebhomengo/niki/repository/migrator"
|
||||||
"git.gocasts.ir/ebhomengo/niki/repository/mysql"
|
"git.gocasts.ir/ebhomengo/niki/repository/mysql"
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,48 @@
|
||||||
|
package domain
|
||||||
|
|
||||||
|
import "time"
|
||||||
|
|
||||||
|
type ID uint64
|
||||||
|
|
||||||
|
type CampaignStatus string
|
||||||
|
|
||||||
|
const (
|
||||||
|
CampaignDraft CampaignStatus = "draft"
|
||||||
|
CampaignActive CampaignStatus = "active"
|
||||||
|
CampaignFinished CampaignStatus = "completed"
|
||||||
|
CampaignPaused CampaignStatus = "paused"
|
||||||
|
CampaignCanceled CampaignStatus = "cancelled"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Campaign struct {
|
||||||
|
ID ID `json:"id"`
|
||||||
|
Title string `json:"title"`
|
||||||
|
Description string `json:"description"`
|
||||||
|
GoalAmount float64 `json:"goal_amount"`
|
||||||
|
RaisedAmount float64 `json:"raised_amount"`
|
||||||
|
Status CampaignStatus `json:"status"`
|
||||||
|
CreatedAt time.Time `json:"created_at"`
|
||||||
|
DeadlineAt *time.Time `json:"deadline_at,omitempty"`
|
||||||
|
AdminID ID `json:"creator_id"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Behavior
|
||||||
|
func (c *Campaign) Activate() {
|
||||||
|
if c.Status == CampaignDraft {
|
||||||
|
c.Status = CampaignActive
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Campaign) AddFunds(amount float64) {
|
||||||
|
c.RaisedAmount += amount
|
||||||
|
if c.RaisedAmount >= c.GoalAmount {
|
||||||
|
c.Status = CampaignFinished
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Campaign) IsExpired(now time.Time) bool {
|
||||||
|
if c.DeadlineAt == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return now.After(*c.DeadlineAt)
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,29 @@
|
||||||
|
package mysql
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"git.gocasts.ir/ebhomengo/niki/campaign/entity"
|
||||||
|
richerror "git.gocasts.ir/ebhomengo/niki/pkg/rich_error"
|
||||||
|
"git.gocasts.ir/ebhomengo/niki/repository/mysql"
|
||||||
|
"git.gocasts.ir/ebhomengo/niki/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
type CampaignRepository interface {
|
||||||
|
CreateAndSave(ctx context.Context, campaign *Campaign) error
|
||||||
|
FindByID(ctx context.Context, id ID) (*Campaign, error)
|
||||||
|
List(ctx context.Context, status CampaignStatus, limit, offset int) ([]*Campaign, error)
|
||||||
|
Delete(ctx context.Context, id ID) error
|
||||||
|
Update(ctx context.Context, campaign *Campaign) error
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -0,0 +1,7 @@
|
||||||
|
package domain
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
@ -0,0 +1,81 @@
|
||||||
|
package campaign
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"errors" // For standard errors
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"your_project/domain"
|
||||||
|
"your_project/pkg/richerror"
|
||||||
|
"your_project/repository"
|
||||||
|
)
|
||||||
|
|
||||||
|
type ID = unit64
|
||||||
|
type EntityCampaign = domain.Campaign
|
||||||
|
|
||||||
|
|
||||||
|
type CampaignServiceImp interface {
|
||||||
|
CreateCampaign(ctx context.Context, req CampaignRepository) (types.ID, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
type CampaignService struct {
|
||||||
|
repo repository.CampaignRepository
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewCampaignService(
|
||||||
|
campaignRepo repository.CampaignRepository,
|
||||||
|
) *CampaignService {
|
||||||
|
return &CampaignService{
|
||||||
|
repo: campaignRepo,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
func (s *CampaignService) CreateCampaign(ctx context.Context, req CreateCampaignRequest) (ID, error) {
|
||||||
|
const Op = "service.campaign.create_campaign"
|
||||||
|
|
||||||
|
if req.Title == "" {
|
||||||
|
return 0, richerror.New(Op).WithMessage("title is required")
|
||||||
|
}
|
||||||
|
if req.GoalAmount <= 0 {
|
||||||
|
return 0, richerror.New(Op).WithMessage("goal_amount must be greater than 0")
|
||||||
|
}
|
||||||
|
if req.AdminID == 0 {
|
||||||
|
return 0, richerror.New(Op).WithMessage("admin_id is required")
|
||||||
|
}
|
||||||
|
|
||||||
|
validStatuses := map[string]bool{
|
||||||
|
"draft": true,
|
||||||
|
"active": true,
|
||||||
|
"completed": true,
|
||||||
|
"cancelled": true,
|
||||||
|
"paused": true
|
||||||
|
}
|
||||||
|
if !validStatuses[req.Status] {
|
||||||
|
return 0, richerror.New(Op).WithMessage("invalid status provided")
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
newCampaign := &EntityCampaign{
|
||||||
|
Title: req.Title,
|
||||||
|
Description: req.Description,
|
||||||
|
GoalAmount: req.GoalAmount,
|
||||||
|
RaisedAmount: 0, // Initially 0
|
||||||
|
Status: EntityCampaign.Status(req.Status),
|
||||||
|
DeadlineAt: req.DeadlineAt,
|
||||||
|
AdminID: req.AdminID,
|
||||||
|
CreatedAt: time.Now(),
|
||||||
|
}
|
||||||
|
|
||||||
|
createdCampaignID, err := s.repo.CreateAndSave(ctx, newCampaign)
|
||||||
|
if err != nil {
|
||||||
|
return 0, richerror.New(Op).WithErr(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return createdCampaignID, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -0,0 +1,49 @@
|
||||||
|
package entity
|
||||||
|
|
||||||
|
import (
|
||||||
|
"git.gocasts.ir/ebhomengo/niki/types"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Order struct {
|
||||||
|
ID types.ID
|
||||||
|
UserID types.ID
|
||||||
|
TotalAmount types.Price
|
||||||
|
TotalDiscount types.Price
|
||||||
|
ShippingID types.ID
|
||||||
|
PaymentMethod PaymentMethod
|
||||||
|
ProcessStatus ProcessStatus
|
||||||
|
PaymentStatus PaymentStatus
|
||||||
|
AddressID types.ID
|
||||||
|
CreatedAt time.Time
|
||||||
|
UpdatedAt time.Time
|
||||||
|
}
|
||||||
|
|
||||||
|
type PaymentMethod string
|
||||||
|
|
||||||
|
const (
|
||||||
|
Online PaymentMethod = "online"
|
||||||
|
Wallet = "wallet"
|
||||||
|
Cart = "cart"
|
||||||
|
)
|
||||||
|
|
||||||
|
type ProcessStatus string
|
||||||
|
|
||||||
|
const (
|
||||||
|
WaitingToPay ProcessStatus = "waiting-to-pay"
|
||||||
|
Processing = "processing"
|
||||||
|
Accepted = "accepted"
|
||||||
|
Preparing = "preparing"
|
||||||
|
Prepared = "prepared"
|
||||||
|
GivenToPost = "given-to-post"
|
||||||
|
Delivered = "delivered"
|
||||||
|
Cancelled = "cancelled"
|
||||||
|
SystemCancellation = "system-cancellation"
|
||||||
|
)
|
||||||
|
|
||||||
|
type PaymentStatus string
|
||||||
|
|
||||||
|
const (
|
||||||
|
Paid PaymentStatus = "paid"
|
||||||
|
UnPaid = "unpaid"
|
||||||
|
)
|
||||||
|
|
@ -0,0 +1,16 @@
|
||||||
|
package entity
|
||||||
|
|
||||||
|
import (
|
||||||
|
"git.gocasts.ir/ebhomengo/niki/types"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
type OrderItem struct {
|
||||||
|
ID types.ID
|
||||||
|
ProductID types.ID
|
||||||
|
Price types.Price
|
||||||
|
Quantity types.Count
|
||||||
|
PriceWithDiscount types.Price
|
||||||
|
OrderID types.ID
|
||||||
|
CreatedAt time.Time
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,10 @@
|
||||||
|
package entity
|
||||||
|
|
||||||
|
import "git.gocasts.ir/ebhomengo/niki/types"
|
||||||
|
|
||||||
|
type Shipping struct {
|
||||||
|
ID types.ID
|
||||||
|
Name string
|
||||||
|
Price types.Price
|
||||||
|
IsActive bool
|
||||||
|
}
|
||||||
|
|
@ -3,11 +3,11 @@
|
||||||
-- https://www.grouparoo.com/blog/varchar-191#why-varchar-and-not-text
|
-- https://www.grouparoo.com/blog/varchar-191#why-varchar-and-not-text
|
||||||
CREATE TABLE `orders` (
|
CREATE TABLE `orders` (
|
||||||
`id` INT PRIMARY KEY AUTO_INCREMENT,
|
`id` INT PRIMARY KEY AUTO_INCREMENT,
|
||||||
`user_id` INT NOT NULL,
|
`user_id` INT,
|
||||||
`address` TEXT,
|
`address_id` INT,
|
||||||
`shipping_id` INT NOT NULL,
|
`shipping_id` INT NOT NULL,
|
||||||
`payment_method` ENUM('online', 'wallet', 'cart') DEFAULT 'online',
|
`payment_method` ENUM('online', 'wallet', 'cart') DEFAULT 'online',
|
||||||
`payment_status` ENUM('unpaid', 'paid', 'cancelled') DEFAULT 'unpaid',
|
`payment_status` ENUM('unpaid', 'paid') DEFAULT 'unpaid',
|
||||||
`process_status` ENUM('waiting-to-pay', 'processing', 'accepted', 'preparing', 'prepared', 'given-to-post', 'delivered', 'cancelled') DEFAULT 'waiting-to-pay',
|
`process_status` ENUM('waiting-to-pay', 'processing', 'accepted', 'preparing', 'prepared', 'given-to-post', 'delivered', 'cancelled') DEFAULT 'waiting-to-pay',
|
||||||
`total_amount` INT NOT NULL,
|
`total_amount` INT NOT NULL,
|
||||||
`total_discount` INT NULL,
|
`total_discount` INT NULL,
|
||||||
|
|
@ -15,7 +15,7 @@ CREATE TABLE `orders` (
|
||||||
`created_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
`created_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||||
`updated_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
|
`updated_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
|
||||||
-- FOREIGN KEY (`user_id`) REFERENCES `users`(`id`)
|
-- FOREIGN KEY (`user_id`) REFERENCES `users`(`id`)
|
||||||
-- FOREIGN KEY (`shipping_id`) REFERENCES `shippings`(`id`)
|
FOREIGN KEY (`shipping_id`) REFERENCES `shippings`(`id`)
|
||||||
|
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
@ -0,0 +1,16 @@
|
||||||
|
-- +migrate Up
|
||||||
|
-- please read this article to understand why we use VARCHAR(191)
|
||||||
|
-- https://www.grouparoo.com/blog/varchar-191#why-varchar-and-not-text
|
||||||
|
CREATE TABLE `orders` (
|
||||||
|
`id` INT PRIMARY KEY AUTO_INCREMENT,
|
||||||
|
`name` VARCHAR (191),
|
||||||
|
`price` INT NOT NULL ,
|
||||||
|
`is_active` INT NOT NULL DEFAULT 1,
|
||||||
|
|
||||||
|
`created_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
`updated_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
|
||||||
|
|
||||||
|
);
|
||||||
|
|
||||||
|
-- +migrate Down
|
||||||
|
DROP TABLE `orders`;
|
||||||
|
|
@ -0,0 +1,11 @@
|
||||||
|
package mysql
|
||||||
|
|
||||||
|
import "git.gocasts.ir/ebhomengo/niki/repository/mysql"
|
||||||
|
|
||||||
|
type DB struct {
|
||||||
|
conn *mysql.DB
|
||||||
|
}
|
||||||
|
|
||||||
|
func New(db *mysql.DB) *DB {
|
||||||
|
return &DB{conn: db}
|
||||||
|
}
|
||||||
|
|
@ -1,23 +1,14 @@
|
||||||
package mysql
|
package mysql
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
entity "git.gocasts.ir/ebhomengo/niki/domain/order/entity"
|
||||||
richerror "git.gocasts.ir/ebhomengo/niki/pkg/rich_error"
|
richerror "git.gocasts.ir/ebhomengo/niki/pkg/rich_error"
|
||||||
"git.gocasts.ir/ebhomengo/niki/purchaseapp/entity"
|
|
||||||
"git.gocasts.ir/ebhomengo/niki/repository/mysql"
|
|
||||||
"git.gocasts.ir/ebhomengo/niki/types"
|
"git.gocasts.ir/ebhomengo/niki/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
type DB struct {
|
|
||||||
conn *mysql.DB
|
|
||||||
}
|
|
||||||
|
|
||||||
func New(db *mysql.DB) *DB {
|
|
||||||
return &DB{conn: db}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *DB) CreateOrder(order entity.Order, orderItems []entity.OrderItem) (types.ID, error) {
|
func (d *DB) CreateOrder(order entity.Order, orderItems []entity.OrderItem) (types.ID, error) {
|
||||||
|
|
||||||
const Op = "repository.mysql.order.createorder"
|
const Op = "domain.repository.mysql.order.create-order"
|
||||||
tx, err := d.conn.Conn().Begin()
|
tx, err := d.conn.Conn().Begin()
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -26,10 +17,10 @@ func (d *DB) CreateOrder(order entity.Order, orderItems []entity.OrderItem) (typ
|
||||||
|
|
||||||
defer tx.Rollback()
|
defer tx.Rollback()
|
||||||
|
|
||||||
query := "insert into orders(user_id, address, shipping_id," +
|
query := "insert into orders(user_id, address_id, shipping_id," +
|
||||||
" payment_method, payment_status, process_status," +
|
" payment_method, payment_status, process_status," +
|
||||||
" total_amount, total_discount) values (?, ?, ?, ?, ?, ?, ?, ?);"
|
" total_amount, total_discount) values (?, ?, ?, ?, ?, ?, ?, ?);"
|
||||||
res, oErr := tx.Exec(query, order.UserID, order.Address, order.ShippingID,
|
res, oErr := tx.Exec(query, order.UserID, order.AddressID, order.ShippingID,
|
||||||
order.PaymentMethod, order.PaymentStatus, order.ProcessStatus,
|
order.PaymentMethod, order.PaymentStatus, order.ProcessStatus,
|
||||||
order.TotalAmount, order.TotalDiscount)
|
order.TotalAmount, order.TotalDiscount)
|
||||||
|
|
||||||
|
|
@ -57,7 +48,7 @@ func (d *DB) CreateOrder(order entity.Order, orderItems []entity.OrderItem) (typ
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *DB) UpdateOrderProcessStatus(orderID types.ID, status string) (bool, error) {
|
func (d *DB) UpdateOrderProcessStatus(orderID types.ID, status string) (bool, error) {
|
||||||
const Op = "repository.mysql.order.update-order-process-status"
|
const Op = "domain.repository.mysql.order.update-order-process-status"
|
||||||
_, err := d.conn.Conn().Exec("update orders set process_status=? where id=?;", status, orderID)
|
_, err := d.conn.Conn().Exec("update orders set process_status=? where id=?;", status, orderID)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -67,3 +58,35 @@ func (d *DB) UpdateOrderProcessStatus(orderID types.ID, status string) (bool, er
|
||||||
return true, nil
|
return true, nil
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (d *DB) GetShipping() ([]entity.Shipping, error) {
|
||||||
|
const Op = "domain.repository.mysql.order.get-shipping"
|
||||||
|
rows, err := d.conn.Conn().Query("select * from shippings where is_active=1")
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return []entity.Shipping{}, richerror.New(Op).WithErr(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
defer rows.Close()
|
||||||
|
|
||||||
|
var shippings []entity.Shipping
|
||||||
|
|
||||||
|
for rows.Next() {
|
||||||
|
var s entity.Shipping
|
||||||
|
|
||||||
|
err := rows.Scan(
|
||||||
|
&s.ID,
|
||||||
|
&s.Name,
|
||||||
|
&s.Price,
|
||||||
|
&s.IsActive,
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return nil, richerror.New(Op).WithErr(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
shippings = append(shippings, s)
|
||||||
|
}
|
||||||
|
|
||||||
|
return shippings, nil
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -1,9 +1,9 @@
|
||||||
package order
|
package service
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
entity "git.gocasts.ir/ebhomengo/niki/domain/order/entity"
|
||||||
richerror "git.gocasts.ir/ebhomengo/niki/pkg/rich_error"
|
richerror "git.gocasts.ir/ebhomengo/niki/pkg/rich_error"
|
||||||
"git.gocasts.ir/ebhomengo/niki/purchaseapp/entity"
|
types "git.gocasts.ir/ebhomengo/niki/types"
|
||||||
"git.gocasts.ir/ebhomengo/niki/types"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type Service struct {
|
type Service struct {
|
||||||
|
|
@ -13,26 +13,27 @@ type Service struct {
|
||||||
type Repo interface {
|
type Repo interface {
|
||||||
CreateOrder(order entity.Order, orderItems []entity.OrderItem) (types.ID, error)
|
CreateOrder(order entity.Order, orderItems []entity.OrderItem) (types.ID, error)
|
||||||
UpdateOrderProcessStatus(orderID types.ID, status string) (bool, error)
|
UpdateOrderProcessStatus(orderID types.ID, status string) (bool, error)
|
||||||
|
GetShipping() ([]entity.Shipping, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
func New(orderRepo Repo) Service {
|
func New(orderRepo Repo) Service {
|
||||||
return Service{repo: orderRepo}
|
return Service{repo: orderRepo}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s Service) CreateOrder(order entity.Order, orderItems []entity.OrderItem) (CreateOrderResponse, error) {
|
func (s *Service) CreateOrder(order entity.Order, orderItems []entity.OrderItem) (types.ID, error) {
|
||||||
const Op = "purchaseapp.service.CreateOrder"
|
const Op = "domain.order.service.order.CreateOrder"
|
||||||
orderID, err := s.repo.CreateOrder(order, orderItems)
|
orderID, err := s.repo.CreateOrder(order, orderItems)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return CreateOrderResponse{}, richerror.New(Op).WithErr(err)
|
return 0, richerror.New(Op).WithErr(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return CreateOrderResponse{OrderID: orderID}, nil
|
return orderID, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s Service) UpdateOrderProcessStatus(orderID types.ID, status string) (bool, error) {
|
func (s *Service) UpdateOrderProcessStatus(orderID types.ID, status string) (bool, error) {
|
||||||
|
|
||||||
const Op = "purchaseapp.service.UpdateOrderProcessStatus"
|
const Op = "domain.order.service.order.UpdateOrderProcessStatus"
|
||||||
_, err := s.repo.UpdateOrderProcessStatus(orderID, status)
|
_, err := s.repo.UpdateOrderProcessStatus(orderID, status)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, richerror.New(Op).WithErr(err)
|
return false, richerror.New(Op).WithErr(err)
|
||||||
|
|
@ -0,0 +1,16 @@
|
||||||
|
package service
|
||||||
|
|
||||||
|
import (
|
||||||
|
"git.gocasts.ir/ebhomengo/niki/domain/order/entity"
|
||||||
|
richerror "git.gocasts.ir/ebhomengo/niki/pkg/rich_error"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (s *Service) GetShipping() ([]entity.Shipping, error) {
|
||||||
|
const Op = "domain.order.service.shipping.get-shipping"
|
||||||
|
shippings, err := s.repo.GetShipping()
|
||||||
|
if err != nil {
|
||||||
|
return []entity.Shipping{}, richerror.New(Op)
|
||||||
|
}
|
||||||
|
|
||||||
|
return shippings, nil
|
||||||
|
}
|
||||||
|
|
@ -16,8 +16,10 @@ func New(db *mysql.DB) *DB {
|
||||||
return &DB{conn: db}
|
return &DB{conn: db}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// CreateCampaign creates a new campaign
|
// CreateCampaign creates a new campaign
|
||||||
func (d *DB) CreateCampaign(ctx context.Context, campaign entity.Campaign) (types.ID, error) {
|
func (d *DB) CreateAndSave(ctx context.Context, campaign entity.Campaign) (types.ID, error) {
|
||||||
const Op = "repository.mysql.campaign.create"
|
const Op = "repository.mysql.campaign.create"
|
||||||
|
|
||||||
tx, err := d.conn.Conn().BeginTx(ctx, nil)
|
tx, err := d.conn.Conn().BeginTx(ctx, nil)
|
||||||
|
|
@ -58,6 +60,8 @@ func (d *DB) CreateCampaign(ctx context.Context, campaign entity.Campaign) (type
|
||||||
return types.ID(campaignID), nil
|
return types.ID(campaignID), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Create adds a new participant to a campaign
|
// Create adds a new participant to a campaign
|
||||||
func (d *DB) CreateCampaignParticipants(ctx context.Context, participant entity.CampaignParticipant) (types.ID, error) {
|
func (d *DB) CreateCampaignParticipants(ctx context.Context, participant entity.CampaignParticipant) (types.ID, error) {
|
||||||
const Op = "repository.mysql.campaign_participant.create"
|
const Op = "repository.mysql.campaign_participant.create"
|
||||||
|
|
|
||||||
|
|
@ -1,30 +0,0 @@
|
||||||
package service
|
|
||||||
|
|
||||||
import (
|
|
||||||
"time"
|
|
||||||
)
|
|
||||||
|
|
||||||
// CampaignStatus represents the possible states of a campaign
|
|
||||||
type CampaignStatus string
|
|
||||||
|
|
||||||
const (
|
|
||||||
StatusActive CampaignStatus = "active"
|
|
||||||
StatusCompleted CampaignStatus = "completed"
|
|
||||||
StatusCancelled CampaignStatus = "cancelled"
|
|
||||||
StatusExpired CampaignStatus = "expired" // New status for deadlines
|
|
||||||
)
|
|
||||||
|
|
||||||
type ID uint64
|
|
||||||
|
|
||||||
type Campaign struct {
|
|
||||||
ID ID `json:"id"`
|
|
||||||
Title string `json:"title"`
|
|
||||||
Description string `json:"description"`
|
|
||||||
GoalAmount float64 `json:"goal_amount"`
|
|
||||||
RaisedAmount float64 `json:"raised_amount"`
|
|
||||||
Status CampaignStatus `json:"status"`
|
|
||||||
CreatedAt time.Time `json:"created_at"`
|
|
||||||
DeadlineAt *time.Time `json:"deadline_at,omitempty"`
|
|
||||||
|
|
||||||
AdminID ID `json:"creator_id"`
|
|
||||||
}
|
|
||||||
|
|
@ -18,16 +18,14 @@ import (
|
||||||
|
|
||||||
|
|
||||||
type CampaignService struct {
|
type CampaignService struct {
|
||||||
repo repository.CampaignRepository
|
repo repository.repo
|
||||||
participantRepo repository.CampaignParticipantRepository
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
type CampaignServiceInterface interface {
|
// type CampaignServiceInterface interface {
|
||||||
CreateCampaign(ctx context.Context, req CampaignRepository) (types.ID, error)
|
// CreateCampaign(ctx context.Context, req CampaignRepository) (types.ID, error)
|
||||||
}
|
// }
|
||||||
|
|
||||||
// NewCampaignService creates a new campaign service
|
|
||||||
func NewCampaignService(
|
func NewCampaignService(
|
||||||
repo repository.CampaignRepository,
|
repo repository.CampaignRepository,
|
||||||
participantRepo repository.CampaignParticipantRepository,
|
participantRepo repository.CampaignParticipantRepository,
|
||||||
|
|
@ -38,54 +36,3 @@ func NewCampaignService(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// CreateCampaign creates a new campaign
|
|
||||||
func (s *CampaignService) CreateCampaign(ctx context.Context, req CreateCampaignRequest) (types.ID, error) {
|
|
||||||
const Op = "service.campaign.create_campaign"
|
|
||||||
|
|
||||||
// Business Logic: Validation
|
|
||||||
if req.Title == "" {
|
|
||||||
return 0, richerror.New(Op).WithErr(errors.New("title is required"))
|
|
||||||
}
|
|
||||||
|
|
||||||
if req.GoalAmount <= 0 {
|
|
||||||
return 0, richerror.New(Op).WithErr(errors.New("goal_amount must be greater than 0"))
|
|
||||||
}
|
|
||||||
|
|
||||||
if req.AdminID == 0 {
|
|
||||||
return 0, richerror.New(Op).WithErr(errors.New("admin_id is required"))
|
|
||||||
}
|
|
||||||
|
|
||||||
// Business Logic: Validate status
|
|
||||||
validStatuses := map[string]bool{
|
|
||||||
"draft": true,
|
|
||||||
"active": true,
|
|
||||||
"completed": true,
|
|
||||||
"cancelled": true,
|
|
||||||
}
|
|
||||||
|
|
||||||
if !validStatuses[req.Status] {
|
|
||||||
return 0, richerror.New(Op).WithErr(errors.New("invalid status"))
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Create campaign entity
|
|
||||||
campaign := entity.Campaign{
|
|
||||||
Title: req.Title,
|
|
||||||
Description: req.Description,
|
|
||||||
GoalAmount: req.GoalAmount,
|
|
||||||
RaisedAmount: 0, // Initially 0
|
|
||||||
Status: entity.CampaignStatus(req.Status),
|
|
||||||
DeadlineAt: req.DeadlineAt,
|
|
||||||
AdminID: req.AdminID,
|
|
||||||
CreatedAt: time.Now(),
|
|
||||||
}
|
|
||||||
|
|
||||||
// Call repository
|
|
||||||
campaignID, err := s.repo.CreateCampaign(ctx, campaign)
|
|
||||||
if err != nil {
|
|
||||||
return 0, richerror.New(Op).WithErr(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return campaignID, nil
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -3,17 +3,17 @@ package patientapp
|
||||||
import (
|
import (
|
||||||
"git.gocasts.ir/ebhomengo/niki/patientapp/config"
|
"git.gocasts.ir/ebhomengo/niki/patientapp/config"
|
||||||
"git.gocasts.ir/ebhomengo/niki/patientapp/delivery/http/analytic"
|
"git.gocasts.ir/ebhomengo/niki/patientapp/delivery/http/analytic"
|
||||||
"git.gocasts.ir/ebhomengo/niki/patientapp/repository/mysql"
|
"git.gocasts.ir/ebhomengo/niki/repository/mysql"
|
||||||
"github.com/labstack/echo/v4"
|
"github.com/labstack/echo/v4"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Application struct {
|
type Application struct {
|
||||||
//Config Config
|
//Config Config
|
||||||
HTTPServer *config.EchoServer
|
HTTPServer *config.EchoServer
|
||||||
DB *mysql.DataBase
|
DB *mysql.DB
|
||||||
}
|
}
|
||||||
|
|
||||||
func Setup(cfg config.Config, conn *mysql.DataBase) Application {
|
func Setup(cfg config.Config, db *mysql.DB) Application {
|
||||||
|
|
||||||
e := echo.New()
|
e := echo.New()
|
||||||
|
|
||||||
|
|
@ -25,13 +25,13 @@ func Setup(cfg config.Config, conn *mysql.DataBase) Application {
|
||||||
return Application{
|
return Application{
|
||||||
//Config: config,
|
//Config: config,
|
||||||
HTTPServer: &server,
|
HTTPServer: &server,
|
||||||
DB: conn,
|
DB: db,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a Application) Start() {
|
func (a Application) Start() {
|
||||||
|
|
||||||
server := analytic.NewServer(a.HTTPServer)
|
server := analytic.NewServer(a.HTTPServer, a.DB)
|
||||||
|
|
||||||
_ = server.Serve()
|
_ = server.Serve()
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,15 +1,26 @@
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"os"
|
||||||
|
"strconv"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"git.gocasts.ir/ebhomengo/niki/patientapp"
|
"git.gocasts.ir/ebhomengo/niki/patientapp"
|
||||||
"git.gocasts.ir/ebhomengo/niki/patientapp/config"
|
"git.gocasts.ir/ebhomengo/niki/patientapp/config"
|
||||||
"git.gocasts.ir/ebhomengo/niki/patientapp/repository/mysql"
|
"git.gocasts.ir/ebhomengo/niki/repository/mysql"
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
db := mysql.DataBase{}
|
dbConf := mysql.Config{
|
||||||
|
Username: os.Getenv("DB_USER"),
|
||||||
|
Password: os.Getenv("DB_PASS"),
|
||||||
|
Host: os.Getenv("DB_HOST"),
|
||||||
|
DBName: os.Getenv("DB_NAME"),
|
||||||
|
}
|
||||||
|
port, _ := strconv.Atoi(os.Getenv("DB_PORT"))
|
||||||
|
dbConf.Port = port
|
||||||
|
|
||||||
|
db := mysql.New(dbConf)
|
||||||
|
|
||||||
cfg := config.Config{
|
cfg := config.Config{
|
||||||
Port: 8080,
|
Port: 8080,
|
||||||
|
|
@ -19,7 +30,7 @@ func main() {
|
||||||
ShutDownCtxTimeout: 5 * time.Second,
|
ShutDownCtxTimeout: 5 * time.Second,
|
||||||
}
|
}
|
||||||
|
|
||||||
app := patientapp.Setup(cfg, &db)
|
app := patientapp.Setup(cfg, db)
|
||||||
|
|
||||||
app.Start()
|
app.Start()
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,15 +1,15 @@
|
||||||
package analytic
|
package analytic
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"git.gocasts.ir/ebhomengo/niki/patientapp/repository/mysql"
|
repo "git.gocasts.ir/ebhomengo/niki/patientapp/repository/mysql"
|
||||||
analytic2 "git.gocasts.ir/ebhomengo/niki/patientapp/service/analytic"
|
analytic2 "git.gocasts.ir/ebhomengo/niki/patientapp/service/analytic"
|
||||||
|
"git.gocasts.ir/ebhomengo/niki/repository/mysql"
|
||||||
"github.com/labstack/echo/v4"
|
"github.com/labstack/echo/v4"
|
||||||
)
|
)
|
||||||
|
|
||||||
func NewPatientAnalyticRouter(s *echo.Group) {
|
func NewPatientAnalyticRouter(s *echo.Group, db *mysql.DB) {
|
||||||
|
|
||||||
mysqlRepo := mysql.NewPatientRepo()
|
mysqlRepo := repo.NewPatientRepo(db)
|
||||||
//rpcRepo := grpc.NewPatientRepo()
|
|
||||||
|
|
||||||
analyticService := analytic2.NewPatientAnalyticService(mysqlRepo)
|
analyticService := analytic2.NewPatientAnalyticService(mysqlRepo)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -5,16 +5,19 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"git.gocasts.ir/ebhomengo/niki/patientapp/config"
|
"git.gocasts.ir/ebhomengo/niki/patientapp/config"
|
||||||
|
"git.gocasts.ir/ebhomengo/niki/repository/mysql"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Server struct {
|
type Server struct {
|
||||||
HTTPServer *config.EchoServer
|
HTTPServer *config.EchoServer
|
||||||
|
Db *mysql.DB
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewServer(server *config.EchoServer) *Server {
|
func NewServer(server *config.EchoServer, db *mysql.DB) *Server {
|
||||||
|
|
||||||
return &Server{
|
return &Server{
|
||||||
HTTPServer: server,
|
HTTPServer: server,
|
||||||
|
Db: db,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -35,7 +38,7 @@ func (s Server) RegisterRoutes() {
|
||||||
{
|
{
|
||||||
// Analytic Group
|
// Analytic Group
|
||||||
analyticGroup := v1.Group("/analytic")
|
analyticGroup := v1.Group("/analytic")
|
||||||
NewPatientAnalyticRouter(analyticGroup)
|
NewPatientAnalyticRouter(analyticGroup, s.Db)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,32 @@
|
||||||
|
version: "3.9"
|
||||||
|
|
||||||
|
services:
|
||||||
|
mysql:
|
||||||
|
image: mysql:8.0
|
||||||
|
container_name: patient
|
||||||
|
restart: unless-stopped
|
||||||
|
environment:
|
||||||
|
MYSQL_ROOT_PASSWORD: rootpass
|
||||||
|
MYSQL_DATABASE: patient
|
||||||
|
MYSQL_USER: appuser
|
||||||
|
MYSQL_PASSWORD: apppass
|
||||||
|
TZ: Asia/Tehran
|
||||||
|
command: [
|
||||||
|
"--character-set-server=utf8mb4",
|
||||||
|
"--collation-server=utf8mb4_unicode_ci",
|
||||||
|
"--default-authentication-plugin=mysql_native_password"
|
||||||
|
]
|
||||||
|
ports:
|
||||||
|
- "3306:3306"
|
||||||
|
volumes:
|
||||||
|
- mysql_data:/var/lib/mysql
|
||||||
|
- ./repository/migration:/docker-entrypoint-initdb.d
|
||||||
|
networks:
|
||||||
|
- backend
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
mysql_data:
|
||||||
|
|
||||||
|
networks:
|
||||||
|
backend:
|
||||||
|
driver: bridge
|
||||||
|
|
@ -0,0 +1,481 @@
|
||||||
|
-- MySQL dump 10.13 Distrib 8.0.29, for Linux (x86_64)
|
||||||
|
--
|
||||||
|
-- Host: localhost Database: patient
|
||||||
|
-- ------------------------------------------------------
|
||||||
|
-- Server version 8.0.29
|
||||||
|
|
||||||
|
/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
|
||||||
|
/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
|
||||||
|
/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
|
||||||
|
/*!50503 SET NAMES utf8mb4 */;
|
||||||
|
/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */;
|
||||||
|
/*!40103 SET TIME_ZONE='+00:00' */;
|
||||||
|
/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
|
||||||
|
/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
|
||||||
|
/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
|
||||||
|
/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Table structure for table `audits`
|
||||||
|
--
|
||||||
|
|
||||||
|
DROP TABLE IF EXISTS `audits`;
|
||||||
|
/*!40101 SET @saved_cs_client = @@character_set_client */;
|
||||||
|
/*!50503 SET character_set_client = utf8mb4 */;
|
||||||
|
CREATE TABLE `audits` (
|
||||||
|
`id` bigint unsigned NOT NULL AUTO_INCREMENT,
|
||||||
|
`user_type` varchar(191) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
|
||||||
|
`user_id` bigint unsigned DEFAULT NULL,
|
||||||
|
`event` varchar(191) COLLATE utf8mb4_unicode_ci NOT NULL,
|
||||||
|
`auditable_type` varchar(191) COLLATE utf8mb4_unicode_ci NOT NULL,
|
||||||
|
`auditable_id` bigint unsigned NOT NULL,
|
||||||
|
`old_values` text COLLATE utf8mb4_unicode_ci,
|
||||||
|
`new_values` text COLLATE utf8mb4_unicode_ci,
|
||||||
|
`url` text COLLATE utf8mb4_unicode_ci,
|
||||||
|
`ip_address` varchar(45) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
|
||||||
|
`user_agent` varchar(1023) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
|
||||||
|
`tags` varchar(191) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
|
||||||
|
`created_at` timestamp NULL DEFAULT NULL,
|
||||||
|
`updated_at` timestamp NULL DEFAULT NULL,
|
||||||
|
PRIMARY KEY (`id`),
|
||||||
|
KEY `audits_auditable_type_auditable_id_index` (`auditable_type`,`auditable_id`),
|
||||||
|
KEY `audits_user_id_user_type_index` (`user_id`,`user_type`)
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||||
|
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Table structure for table `bandage_user`
|
||||||
|
--
|
||||||
|
|
||||||
|
DROP TABLE IF EXISTS `bandage_user`;
|
||||||
|
/*!40101 SET @saved_cs_client = @@character_set_client */;
|
||||||
|
/*!50503 SET character_set_client = utf8mb4 */;
|
||||||
|
CREATE TABLE `bandage_user` (
|
||||||
|
`user_id` bigint unsigned NOT NULL,
|
||||||
|
`bandage_id` bigint unsigned NOT NULL,
|
||||||
|
`qty` int unsigned NOT NULL DEFAULT '0',
|
||||||
|
`created_at` timestamp NULL DEFAULT NULL,
|
||||||
|
`updated_at` timestamp NULL DEFAULT NULL
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||||
|
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Table structure for table `bandages`
|
||||||
|
--
|
||||||
|
|
||||||
|
DROP TABLE IF EXISTS `bandages`;
|
||||||
|
/*!40101 SET @saved_cs_client = @@character_set_client */;
|
||||||
|
/*!50503 SET character_set_client = utf8mb4 */;
|
||||||
|
CREATE TABLE `bandages` (
|
||||||
|
`id` bigint unsigned NOT NULL AUTO_INCREMENT,
|
||||||
|
`name` varchar(191) COLLATE utf8mb4_unicode_ci NOT NULL,
|
||||||
|
`created_at` timestamp NULL DEFAULT NULL,
|
||||||
|
`updated_at` timestamp NULL DEFAULT NULL,
|
||||||
|
PRIMARY KEY (`id`)
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||||
|
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Table structure for table `cities`
|
||||||
|
--
|
||||||
|
|
||||||
|
DROP TABLE IF EXISTS `cities`;
|
||||||
|
/*!40101 SET @saved_cs_client = @@character_set_client */;
|
||||||
|
/*!50503 SET character_set_client = utf8mb4 */;
|
||||||
|
CREATE TABLE `cities` (
|
||||||
|
`id` int unsigned NOT NULL AUTO_INCREMENT,
|
||||||
|
`state_id` int unsigned NOT NULL,
|
||||||
|
`name` varchar(191) COLLATE utf8mb4_unicode_ci NOT NULL,
|
||||||
|
PRIMARY KEY (`id`)
|
||||||
|
) ENGINE=InnoDB AUTO_INCREMENT=445 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||||
|
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Table structure for table `drug_user`
|
||||||
|
--
|
||||||
|
|
||||||
|
DROP TABLE IF EXISTS `drug_user`;
|
||||||
|
/*!40101 SET @saved_cs_client = @@character_set_client */;
|
||||||
|
/*!50503 SET character_set_client = utf8mb4 */;
|
||||||
|
CREATE TABLE `drug_user` (
|
||||||
|
`user_id` bigint unsigned NOT NULL,
|
||||||
|
`drug_id` bigint unsigned NOT NULL,
|
||||||
|
`qty` int unsigned NOT NULL DEFAULT '0',
|
||||||
|
`created_at` timestamp NULL DEFAULT NULL,
|
||||||
|
`updated_at` timestamp NULL DEFAULT NULL
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||||
|
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Table structure for table `drugs`
|
||||||
|
--
|
||||||
|
|
||||||
|
DROP TABLE IF EXISTS `drugs`;
|
||||||
|
/*!40101 SET @saved_cs_client = @@character_set_client */;
|
||||||
|
/*!50503 SET character_set_client = utf8mb4 */;
|
||||||
|
CREATE TABLE `drugs` (
|
||||||
|
`id` bigint unsigned NOT NULL AUTO_INCREMENT,
|
||||||
|
`name` varchar(191) COLLATE utf8mb4_unicode_ci NOT NULL,
|
||||||
|
`created_at` timestamp NULL DEFAULT NULL,
|
||||||
|
`updated_at` timestamp NULL DEFAULT NULL,
|
||||||
|
PRIMARY KEY (`id`)
|
||||||
|
) ENGINE=InnoDB AUTO_INCREMENT=15 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||||
|
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Table structure for table `failed_jobs`
|
||||||
|
--
|
||||||
|
|
||||||
|
DROP TABLE IF EXISTS `failed_jobs`;
|
||||||
|
/*!40101 SET @saved_cs_client = @@character_set_client */;
|
||||||
|
/*!50503 SET character_set_client = utf8mb4 */;
|
||||||
|
CREATE TABLE `failed_jobs` (
|
||||||
|
`id` bigint unsigned NOT NULL AUTO_INCREMENT,
|
||||||
|
`uuid` varchar(191) COLLATE utf8mb4_unicode_ci NOT NULL,
|
||||||
|
`connection` text COLLATE utf8mb4_unicode_ci NOT NULL,
|
||||||
|
`queue` text COLLATE utf8mb4_unicode_ci NOT NULL,
|
||||||
|
`payload` longtext COLLATE utf8mb4_unicode_ci NOT NULL,
|
||||||
|
`exception` longtext COLLATE utf8mb4_unicode_ci NOT NULL,
|
||||||
|
`failed_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
PRIMARY KEY (`id`),
|
||||||
|
UNIQUE KEY `failed_jobs_uuid_unique` (`uuid`)
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||||
|
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Table structure for table `logs`
|
||||||
|
--
|
||||||
|
|
||||||
|
DROP TABLE IF EXISTS `logs`;
|
||||||
|
/*!40101 SET @saved_cs_client = @@character_set_client */;
|
||||||
|
/*!50503 SET character_set_client = utf8mb4 */;
|
||||||
|
CREATE TABLE `logs` (
|
||||||
|
`id` bigint unsigned NOT NULL AUTO_INCREMENT,
|
||||||
|
`user_id` int unsigned NOT NULL,
|
||||||
|
`type` varchar(191) COLLATE utf8mb4_unicode_ci NOT NULL,
|
||||||
|
`log` varchar(191) COLLATE utf8mb4_unicode_ci NOT NULL,
|
||||||
|
`created_at` timestamp NULL DEFAULT NULL,
|
||||||
|
`updated_at` timestamp NULL DEFAULT NULL,
|
||||||
|
PRIMARY KEY (`id`)
|
||||||
|
) ENGINE=InnoDB AUTO_INCREMENT=20739 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||||
|
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Table structure for table `migrations`
|
||||||
|
--
|
||||||
|
|
||||||
|
DROP TABLE IF EXISTS `migrations`;
|
||||||
|
/*!40101 SET @saved_cs_client = @@character_set_client */;
|
||||||
|
/*!50503 SET character_set_client = utf8mb4 */;
|
||||||
|
CREATE TABLE `migrations` (
|
||||||
|
`id` int unsigned NOT NULL AUTO_INCREMENT,
|
||||||
|
`migration` varchar(191) COLLATE utf8mb4_unicode_ci NOT NULL,
|
||||||
|
`batch` int NOT NULL,
|
||||||
|
PRIMARY KEY (`id`)
|
||||||
|
) ENGINE=InnoDB AUTO_INCREMENT=47 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||||
|
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Table structure for table `model_has_permissions`
|
||||||
|
--
|
||||||
|
|
||||||
|
DROP TABLE IF EXISTS `model_has_permissions`;
|
||||||
|
/*!40101 SET @saved_cs_client = @@character_set_client */;
|
||||||
|
/*!50503 SET character_set_client = utf8mb4 */;
|
||||||
|
CREATE TABLE `model_has_permissions` (
|
||||||
|
`permission_id` bigint unsigned NOT NULL,
|
||||||
|
`model_type` varchar(191) COLLATE utf8mb4_unicode_ci NOT NULL,
|
||||||
|
`model_id` bigint unsigned NOT NULL,
|
||||||
|
PRIMARY KEY (`permission_id`,`model_id`,`model_type`),
|
||||||
|
KEY `model_has_permissions_model_id_model_type_index` (`model_id`,`model_type`),
|
||||||
|
CONSTRAINT `model_has_permissions_permission_id_foreign` FOREIGN KEY (`permission_id`) REFERENCES `permissions` (`id`) ON DELETE CASCADE
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||||
|
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Table structure for table `model_has_roles`
|
||||||
|
--
|
||||||
|
|
||||||
|
DROP TABLE IF EXISTS `model_has_roles`;
|
||||||
|
/*!40101 SET @saved_cs_client = @@character_set_client */;
|
||||||
|
/*!50503 SET character_set_client = utf8mb4 */;
|
||||||
|
CREATE TABLE `model_has_roles` (
|
||||||
|
`role_id` bigint unsigned NOT NULL,
|
||||||
|
`model_type` varchar(191) COLLATE utf8mb4_unicode_ci NOT NULL,
|
||||||
|
`model_id` bigint unsigned NOT NULL,
|
||||||
|
PRIMARY KEY (`role_id`,`model_id`,`model_type`),
|
||||||
|
KEY `model_has_roles_model_id_model_type_index` (`model_id`,`model_type`),
|
||||||
|
CONSTRAINT `model_has_roles_role_id_foreign` FOREIGN KEY (`role_id`) REFERENCES `roles` (`id`) ON DELETE CASCADE
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||||
|
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Table structure for table `password_resets`
|
||||||
|
--
|
||||||
|
|
||||||
|
DROP TABLE IF EXISTS `password_resets`;
|
||||||
|
/*!40101 SET @saved_cs_client = @@character_set_client */;
|
||||||
|
/*!50503 SET character_set_client = utf8mb4 */;
|
||||||
|
CREATE TABLE `password_resets` (
|
||||||
|
`id` int unsigned NOT NULL AUTO_INCREMENT,
|
||||||
|
`user_id` bigint DEFAULT NULL,
|
||||||
|
`time` int DEFAULT NULL,
|
||||||
|
`token` varchar(191) COLLATE utf8mb4_unicode_ci NOT NULL,
|
||||||
|
`created_at` timestamp NULL DEFAULT NULL,
|
||||||
|
PRIMARY KEY (`id`)
|
||||||
|
) ENGINE=InnoDB AUTO_INCREMENT=227 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||||
|
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Table structure for table `permissions`
|
||||||
|
--
|
||||||
|
|
||||||
|
DROP TABLE IF EXISTS `permissions`;
|
||||||
|
/*!40101 SET @saved_cs_client = @@character_set_client */;
|
||||||
|
/*!50503 SET character_set_client = utf8mb4 */;
|
||||||
|
CREATE TABLE `permissions` (
|
||||||
|
`id` bigint unsigned NOT NULL AUTO_INCREMENT,
|
||||||
|
`name` varchar(191) COLLATE utf8mb4_unicode_ci NOT NULL,
|
||||||
|
`guard_name` varchar(191) COLLATE utf8mb4_unicode_ci NOT NULL,
|
||||||
|
`created_at` timestamp NULL DEFAULT NULL,
|
||||||
|
`updated_at` timestamp NULL DEFAULT NULL,
|
||||||
|
PRIMARY KEY (`id`)
|
||||||
|
) ENGINE=InnoDB AUTO_INCREMENT=28 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||||
|
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Table structure for table `reports`
|
||||||
|
--
|
||||||
|
|
||||||
|
DROP TABLE IF EXISTS `reports`;
|
||||||
|
/*!40101 SET @saved_cs_client = @@character_set_client */;
|
||||||
|
/*!50503 SET character_set_client = utf8mb4 */;
|
||||||
|
CREATE TABLE `reports` (
|
||||||
|
`id` bigint unsigned NOT NULL AUTO_INCREMENT,
|
||||||
|
`user_id` bigint unsigned NOT NULL,
|
||||||
|
`agent_id` bigint unsigned NOT NULL,
|
||||||
|
`type` varchar(50) COLLATE utf8mb4_unicode_ci NOT NULL,
|
||||||
|
`interviewee` varchar(50) COLLATE utf8mb4_unicode_ci NOT NULL,
|
||||||
|
`interviewee_name` varchar(191) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
|
||||||
|
`interviewee_ratio` varchar(191) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
|
||||||
|
`content` text COLLATE utf8mb4_unicode_ci NOT NULL,
|
||||||
|
`created_at` timestamp NULL DEFAULT NULL,
|
||||||
|
`updated_at` timestamp NULL DEFAULT NULL,
|
||||||
|
PRIMARY KEY (`id`),
|
||||||
|
KEY `reports_user_id_foreign` (`user_id`),
|
||||||
|
CONSTRAINT `reports_user_id_foreign` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`) ON DELETE CASCADE
|
||||||
|
) ENGINE=InnoDB AUTO_INCREMENT=19846 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||||
|
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Table structure for table `role_has_permissions`
|
||||||
|
--
|
||||||
|
|
||||||
|
DROP TABLE IF EXISTS `role_has_permissions`;
|
||||||
|
/*!40101 SET @saved_cs_client = @@character_set_client */;
|
||||||
|
/*!50503 SET character_set_client = utf8mb4 */;
|
||||||
|
CREATE TABLE `role_has_permissions` (
|
||||||
|
`permission_id` bigint unsigned NOT NULL,
|
||||||
|
`role_id` bigint unsigned NOT NULL,
|
||||||
|
PRIMARY KEY (`permission_id`,`role_id`),
|
||||||
|
KEY `role_has_permissions_role_id_foreign` (`role_id`),
|
||||||
|
CONSTRAINT `role_has_permissions_permission_id_foreign` FOREIGN KEY (`permission_id`) REFERENCES `permissions` (`id`) ON DELETE CASCADE,
|
||||||
|
CONSTRAINT `role_has_permissions_role_id_foreign` FOREIGN KEY (`role_id`) REFERENCES `roles` (`id`) ON DELETE CASCADE
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||||
|
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Table structure for table `roles`
|
||||||
|
--
|
||||||
|
|
||||||
|
DROP TABLE IF EXISTS `roles`;
|
||||||
|
/*!40101 SET @saved_cs_client = @@character_set_client */;
|
||||||
|
/*!50503 SET character_set_client = utf8mb4 */;
|
||||||
|
CREATE TABLE `roles` (
|
||||||
|
`id` bigint unsigned NOT NULL AUTO_INCREMENT,
|
||||||
|
`name` varchar(191) COLLATE utf8mb4_unicode_ci NOT NULL,
|
||||||
|
`guard_name` varchar(191) COLLATE utf8mb4_unicode_ci NOT NULL,
|
||||||
|
`created_at` timestamp NULL DEFAULT NULL,
|
||||||
|
`updated_at` timestamp NULL DEFAULT NULL,
|
||||||
|
PRIMARY KEY (`id`)
|
||||||
|
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||||
|
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Table structure for table `states`
|
||||||
|
--
|
||||||
|
|
||||||
|
DROP TABLE IF EXISTS `states`;
|
||||||
|
/*!40101 SET @saved_cs_client = @@character_set_client */;
|
||||||
|
/*!50503 SET character_set_client = utf8mb4 */;
|
||||||
|
CREATE TABLE `states` (
|
||||||
|
`id` int unsigned NOT NULL AUTO_INCREMENT,
|
||||||
|
`name` varchar(191) COLLATE utf8mb4_unicode_ci NOT NULL,
|
||||||
|
PRIMARY KEY (`id`)
|
||||||
|
) ENGINE=InnoDB AUTO_INCREMENT=32 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||||
|
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Table structure for table `user_files`
|
||||||
|
--
|
||||||
|
|
||||||
|
DROP TABLE IF EXISTS `user_files`;
|
||||||
|
/*!40101 SET @saved_cs_client = @@character_set_client */;
|
||||||
|
/*!50503 SET character_set_client = utf8mb4 */;
|
||||||
|
CREATE TABLE `user_files` (
|
||||||
|
`id` bigint unsigned NOT NULL AUTO_INCREMENT,
|
||||||
|
`user_id` bigint unsigned NOT NULL,
|
||||||
|
`name` varchar(191) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
|
||||||
|
`type` varchar(50) COLLATE utf8mb4_unicode_ci NOT NULL,
|
||||||
|
`label` varchar(150) COLLATE utf8mb4_unicode_ci NOT NULL,
|
||||||
|
`status` varchar(50) COLLATE utf8mb4_unicode_ci NOT NULL,
|
||||||
|
`message` varchar(150) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
|
||||||
|
`created_at` timestamp NULL DEFAULT NULL,
|
||||||
|
`updated_at` timestamp NULL DEFAULT NULL,
|
||||||
|
PRIMARY KEY (`id`)
|
||||||
|
) ENGINE=InnoDB AUTO_INCREMENT=40633 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||||
|
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Table structure for table `user_metas`
|
||||||
|
--
|
||||||
|
|
||||||
|
DROP TABLE IF EXISTS `user_metas`;
|
||||||
|
/*!40101 SET @saved_cs_client = @@character_set_client */;
|
||||||
|
/*!50503 SET character_set_client = utf8mb4 */;
|
||||||
|
CREATE TABLE `user_metas` (
|
||||||
|
`id` bigint unsigned NOT NULL AUTO_INCREMENT,
|
||||||
|
`user_id` bigint unsigned NOT NULL,
|
||||||
|
`birthPlaceState` smallint unsigned NOT NULL DEFAULT '0',
|
||||||
|
`birthPlaceCity` smallint unsigned NOT NULL DEFAULT '0',
|
||||||
|
`religion` varchar(50) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
|
||||||
|
`atba` varchar(50) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
|
||||||
|
`nationality` varchar(191) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
|
||||||
|
`atba_birthPlaceState` varchar(191) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
|
||||||
|
`atba_birthPlaceCity` varchar(191) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
|
||||||
|
`height` smallint unsigned DEFAULT NULL,
|
||||||
|
`weight` smallint unsigned DEFAULT NULL,
|
||||||
|
`eyeColor` varchar(50) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
|
||||||
|
`bloodType` varchar(50) COLLATE utf8mb4_unicode_ci NOT NULL,
|
||||||
|
`addressState` smallint unsigned NOT NULL,
|
||||||
|
`addressCity` smallint unsigned NOT NULL,
|
||||||
|
`address` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL,
|
||||||
|
`postalCode` varchar(30) COLLATE utf8mb4_unicode_ci NOT NULL,
|
||||||
|
`phone` varchar(30) COLLATE utf8mb4_unicode_ci NOT NULL,
|
||||||
|
`mobile` varchar(30) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
|
||||||
|
`fMobile` varchar(20) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
|
||||||
|
`mMobile` varchar(20) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
|
||||||
|
`ePhoneName` varchar(100) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
|
||||||
|
`ePhoneNumber` varchar(30) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
|
||||||
|
`houseType` varchar(30) COLLATE utf8mb4_unicode_ci NOT NULL,
|
||||||
|
`housePrice` varchar(30) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
|
||||||
|
`houseMortgage` varchar(30) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
|
||||||
|
`houseRent` varchar(30) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
|
||||||
|
`fAlive` tinyint(1) DEFAULT NULL,
|
||||||
|
`divorced` tinyint(1) NOT NULL DEFAULT '0',
|
||||||
|
`devorced` tinyint NOT NULL DEFAULT '0',
|
||||||
|
`fName` varchar(90) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
|
||||||
|
`fBirthDate` date DEFAULT NULL,
|
||||||
|
`fNationalCode` varchar(191) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
|
||||||
|
`fAtba` tinyint(1) NOT NULL DEFAULT '0',
|
||||||
|
`fNationality` varchar(191) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
|
||||||
|
`fJob` varchar(191) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
|
||||||
|
`fEdu` varchar(90) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
|
||||||
|
`mAlive` tinyint(1) DEFAULT NULL,
|
||||||
|
`mName` varchar(90) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
|
||||||
|
`mBirthDate` date DEFAULT NULL,
|
||||||
|
`mNationalCode` varchar(30) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
|
||||||
|
`mAtba` tinyint(1) NOT NULL DEFAULT '0',
|
||||||
|
`mNationality` varchar(191) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
|
||||||
|
`mJob` varchar(191) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
|
||||||
|
`mEdu` varchar(90) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
|
||||||
|
`ratio` tinyint(1) DEFAULT NULL,
|
||||||
|
`ratioType` varchar(191) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
|
||||||
|
`liveChild` tinyint unsigned NOT NULL,
|
||||||
|
`ebChild` tinyint unsigned NOT NULL,
|
||||||
|
`Edu` varchar(90) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
|
||||||
|
`skills` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
|
||||||
|
`insurance` tinyint(1) NOT NULL,
|
||||||
|
`insuranceYear` tinyint unsigned DEFAULT NULL,
|
||||||
|
`insuranceMonth` tinyint unsigned DEFAULT NULL,
|
||||||
|
`insuranceCoverage` tinyint(1) NOT NULL,
|
||||||
|
`insuranceCoverageNumber` varchar(30) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
|
||||||
|
`insuranceCoveragBranch` varchar(191) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
|
||||||
|
`insuranceCoverageType` varchar(191) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
|
||||||
|
`supplementaryInsurance` tinyint(1) NOT NULL,
|
||||||
|
`supplementaryInsuranceName` varchar(191) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
|
||||||
|
`supportOrganization` tinyint(1) NOT NULL,
|
||||||
|
`supportOrganizationName` varchar(191) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
|
||||||
|
`dailyProblemType` varchar(191) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
|
||||||
|
`description` varchar(500) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
|
||||||
|
`created_at` timestamp NULL DEFAULT NULL,
|
||||||
|
`updated_at` timestamp NULL DEFAULT NULL,
|
||||||
|
`spouseName` varchar(90) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
|
||||||
|
`spouseBirthDate` date DEFAULT NULL,
|
||||||
|
`spouseNationalCode` varchar(191) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
|
||||||
|
`spouseAtba` tinyint(1) NOT NULL DEFAULT '0',
|
||||||
|
`spouseNationality` varchar(191) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
|
||||||
|
`spouseJob` varchar(191) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
|
||||||
|
`spouseEdu` varchar(90) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
|
||||||
|
`spouseMobile` varchar(20) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
|
||||||
|
`spouseAlive` tinyint(1) DEFAULT NULL,
|
||||||
|
`shenasname` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL,
|
||||||
|
`shenasnamePlace` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL,
|
||||||
|
PRIMARY KEY (`id`),
|
||||||
|
KEY `user_metas_user_id_foreign` (`user_id`),
|
||||||
|
CONSTRAINT `user_metas_user_id_foreign` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`) ON DELETE CASCADE
|
||||||
|
) ENGINE=InnoDB AUTO_INCREMENT=1461 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||||
|
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Table structure for table `users`
|
||||||
|
--
|
||||||
|
|
||||||
|
DROP TABLE IF EXISTS `users`;
|
||||||
|
/*!40101 SET @saved_cs_client = @@character_set_client */;
|
||||||
|
/*!50503 SET character_set_client = utf8mb4 */;
|
||||||
|
CREATE TABLE `users` (
|
||||||
|
`id` bigint unsigned NOT NULL AUTO_INCREMENT,
|
||||||
|
`name` varchar(191) COLLATE utf8mb4_unicode_ci NOT NULL,
|
||||||
|
`last_name` varchar(191) COLLATE utf8mb4_unicode_ci NOT NULL,
|
||||||
|
`username` varchar(191) COLLATE utf8mb4_unicode_ci NOT NULL,
|
||||||
|
`password` varchar(191) COLLATE utf8mb4_unicode_ci NOT NULL,
|
||||||
|
`pic` varchar(191) COLLATE utf8mb4_unicode_ci NOT NULL,
|
||||||
|
`birth_date` date DEFAULT NULL,
|
||||||
|
`gender` tinyint(1) NOT NULL,
|
||||||
|
`marital` smallint unsigned DEFAULT NULL,
|
||||||
|
`deceased` date DEFAULT NULL,
|
||||||
|
`seyyed` tinyint(1) NOT NULL DEFAULT '0',
|
||||||
|
`profile_number` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
|
||||||
|
`sheba` varchar(90) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
|
||||||
|
`bank_account` varchar(90) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
|
||||||
|
`bank_account_name` varchar(90) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
|
||||||
|
`profile_status` tinyint unsigned DEFAULT NULL,
|
||||||
|
`medical_information_status` tinyint unsigned DEFAULT NULL,
|
||||||
|
`remember_token` varchar(100) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
|
||||||
|
`created_at` timestamp NULL DEFAULT NULL,
|
||||||
|
`updated_at` timestamp NULL DEFAULT NULL,
|
||||||
|
`drug_description` varchar(191) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
|
||||||
|
`bandage_description` varchar(191) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
|
||||||
|
`bandage_period` tinyint unsigned DEFAULT NULL,
|
||||||
|
`bandage_months` text COLLATE utf8mb4_unicode_ci,
|
||||||
|
`twoFA_enabled` tinyint(1) NOT NULL DEFAULT '0',
|
||||||
|
`twoFA_secret` varchar(191) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
|
||||||
|
`is_active` tinyint(1) NOT NULL DEFAULT '1',
|
||||||
|
PRIMARY KEY (`id`),
|
||||||
|
UNIQUE KEY `users_username_unique` (`username`),
|
||||||
|
KEY `users_twofa_enabled_index` (`twoFA_enabled`),
|
||||||
|
KEY `users_is_active_index` (`is_active`)
|
||||||
|
) ENGINE=InnoDB AUTO_INCREMENT=1918 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||||
|
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||||
|
/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */;
|
||||||
|
|
||||||
|
/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
|
||||||
|
/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;
|
||||||
|
/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */;
|
||||||
|
/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
|
||||||
|
/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
|
||||||
|
/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
|
||||||
|
/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;
|
||||||
|
|
||||||
|
-- Dump completed on 2026-04-14 7:28:21
|
||||||
|
|
@ -1,35 +0,0 @@
|
||||||
package grpc
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
|
|
||||||
"git.gocasts.ir/ebhomengo/niki/patientapp/service/analytic"
|
|
||||||
"git.gocasts.ir/ebhomengo/niki/patientapp/service/entity"
|
|
||||||
)
|
|
||||||
|
|
||||||
type AnalyticRepository struct{}
|
|
||||||
|
|
||||||
func NewPatientRepo() *AnalyticRepository {
|
|
||||||
|
|
||||||
return &AnalyticRepository{}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (db *AnalyticRepository) GetPatients(ctx context.Context, f analytic.PatientFilter) ([]entity.Patient, error) {
|
|
||||||
|
|
||||||
return nil, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (db *AnalyticRepository) CountPatients(ctx context.Context, f analytic.PatientFilter) (int, error) {
|
|
||||||
|
|
||||||
return 0, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (db *AnalyticRepository) SummaryByCity(ctx context.Context, provinceID uint, f analytic.PatientMapFilter) (map[uint][]entity.MapSummaryItem, error) {
|
|
||||||
|
|
||||||
return nil, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (db *AnalyticRepository) SummaryByProvince(ctx context.Context, f analytic.PatientMapFilter) (map[uint][]entity.MapSummaryItem, error) {
|
|
||||||
|
|
||||||
return nil, nil
|
|
||||||
}
|
|
||||||
|
|
@ -2,35 +2,385 @@ package mysql
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
"git.gocasts.ir/ebhomengo/niki/patientapp/service/analytic"
|
"git.gocasts.ir/ebhomengo/niki/patientapp/service/analytic"
|
||||||
"git.gocasts.ir/ebhomengo/niki/patientapp/service/entity"
|
"git.gocasts.ir/ebhomengo/niki/patientapp/service/entity"
|
||||||
|
richerror "git.gocasts.ir/ebhomengo/niki/pkg/rich_error"
|
||||||
|
"git.gocasts.ir/ebhomengo/niki/repository/mysql"
|
||||||
)
|
)
|
||||||
|
|
||||||
type DataBase struct{}
|
type DataBase struct {
|
||||||
|
conn *mysql.DB
|
||||||
func NewPatientRepo() *DataBase {
|
|
||||||
|
|
||||||
return &DataBase{}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (db *DataBase) GetPatients(ctx context.Context, f analytic.PatientFilter) ([]entity.Patient, error) {
|
func NewPatientRepo(db *mysql.DB) *DataBase {
|
||||||
|
|
||||||
return nil, nil
|
return &DataBase{
|
||||||
|
conn: db,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (db *DataBase) GetPatients(ctx context.Context, f analytic.PatientFilter) ([]entity.UserMeta, error) {
|
||||||
|
const Op = "repository.mysql.patient.get"
|
||||||
|
|
||||||
|
tx, err := db.conn.Conn().BeginTx(ctx, nil)
|
||||||
|
if err != nil {
|
||||||
|
return []entity.UserMeta{}, richerror.New(Op).WithErr(err)
|
||||||
|
}
|
||||||
|
defer tx.Rollback()
|
||||||
|
|
||||||
|
query := `
|
||||||
|
SELECT
|
||||||
|
um.id,
|
||||||
|
um.user_id,
|
||||||
|
u.birthDate,
|
||||||
|
u.sex,
|
||||||
|
um.birthPlaceState,
|
||||||
|
um.birthPlaceCity,
|
||||||
|
um.nationality,
|
||||||
|
um.addressState,
|
||||||
|
um.addressCity,
|
||||||
|
um.address,
|
||||||
|
um.phone,
|
||||||
|
um.mobile,
|
||||||
|
um.spouseName,
|
||||||
|
um.created_at,
|
||||||
|
um.updated_at
|
||||||
|
FROM user_metas um
|
||||||
|
JOIN users u ON u.id = um.user_id
|
||||||
|
WHERE 1=1
|
||||||
|
`
|
||||||
|
|
||||||
|
args := []any{}
|
||||||
|
|
||||||
|
// Birthdate filters (FROM = born after)
|
||||||
|
if f.DOBFrom != nil && *f.DOBFrom != "" {
|
||||||
|
query += " AND u.birth_date >= ?"
|
||||||
|
args = append(args, *f.DOBFrom)
|
||||||
|
}
|
||||||
|
if f.DOBTo != nil && *f.DOBTo != "" {
|
||||||
|
query += " AND u.birth_date <= ?"
|
||||||
|
args = append(args, *f.DOBTo)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sex
|
||||||
|
if f.Sex != nil && *f.Sex != "" {
|
||||||
|
query += " AND u.sex = ?"
|
||||||
|
args = append(args, *f.Sex)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Nationality
|
||||||
|
if f.Nationality != "" {
|
||||||
|
query += " AND um.nationality = ?"
|
||||||
|
args = append(args, f.Nationality)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Address
|
||||||
|
if f.AddressState != 0 {
|
||||||
|
query += " AND um.addressState = ?"
|
||||||
|
args = append(args, f.AddressState)
|
||||||
|
}
|
||||||
|
if f.AddressCity != 0 {
|
||||||
|
query += " AND um.addressCity = ?"
|
||||||
|
args = append(args, f.AddressCity)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Search on fields from user_metas and users
|
||||||
|
if f.Search != nil && *f.Search != "" {
|
||||||
|
like := "%" + *f.Search + "%"
|
||||||
|
query += `
|
||||||
|
AND (
|
||||||
|
um.fName LIKE ? OR
|
||||||
|
um.mName LIKE ? OR
|
||||||
|
um.spouseName LIKE ? OR
|
||||||
|
um.phone LIKE ? OR
|
||||||
|
um.mobile LIKE ?
|
||||||
|
)
|
||||||
|
`
|
||||||
|
args = append(args, like, like, like, like, like)
|
||||||
|
}
|
||||||
|
|
||||||
|
query += " ORDER BY id DESC"
|
||||||
|
|
||||||
|
if f.Limit > 0 {
|
||||||
|
query += " LIMIT ?"
|
||||||
|
args = append(args, f.Limit)
|
||||||
|
}
|
||||||
|
if f.Offset > 0 {
|
||||||
|
query += " OFFSET ?"
|
||||||
|
args = append(args, f.Offset)
|
||||||
|
}
|
||||||
|
|
||||||
|
rows, err := tx.QueryContext(ctx, query, args...)
|
||||||
|
if err != nil {
|
||||||
|
|
||||||
|
return nil, richerror.New(Op).WithErr(err)
|
||||||
|
}
|
||||||
|
defer rows.Close()
|
||||||
|
|
||||||
|
var result []entity.UserMeta
|
||||||
|
|
||||||
|
for rows.Next() {
|
||||||
|
var u entity.UserMeta
|
||||||
|
if err := rows.Scan(
|
||||||
|
&u.ID, &u.UserID, &u.BirthDate, &u.Gender, &u.BirthPlaceState, &u.BirthPlaceCity,
|
||||||
|
&u.Religion, &u.Nationality, &u.AddressState, &u.AddressCity,
|
||||||
|
&u.Address, &u.Mobile, &u.SpouseName, &u.SpouseAlive,
|
||||||
|
&u.CreatedAt, &u.UpdatedAt,
|
||||||
|
); err != nil {
|
||||||
|
return nil, richerror.New(Op).WithErr(err)
|
||||||
|
}
|
||||||
|
result = append(result, u)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := rows.Err(); err != nil {
|
||||||
|
return nil, richerror.New(Op).WithErr(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return result, nil
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (db *DataBase) CountPatients(ctx context.Context, f analytic.PatientFilter) (int, error) {
|
func (db *DataBase) CountPatients(ctx context.Context, f analytic.PatientFilter) (int, error) {
|
||||||
|
const Op = "repository.mysql.patient.count"
|
||||||
|
|
||||||
return 0, nil
|
tx, err := db.conn.Conn().BeginTx(ctx, nil)
|
||||||
|
if err != nil {
|
||||||
|
return 0, richerror.New(Op).WithErr(err)
|
||||||
|
}
|
||||||
|
defer tx.Rollback()
|
||||||
|
|
||||||
|
query := `
|
||||||
|
SELECT COUNT(*)
|
||||||
|
FROM user_metas um
|
||||||
|
JOIN users u ON u.id = um.user_id
|
||||||
|
WHERE 1=1
|
||||||
|
`
|
||||||
|
|
||||||
|
args := []any{}
|
||||||
|
|
||||||
|
// Birthdate range
|
||||||
|
if f.DOBFrom != nil && *f.DOBFrom != "" {
|
||||||
|
query += " AND u.birth_date >= ?"
|
||||||
|
args = append(args, *f.DOBFrom)
|
||||||
|
}
|
||||||
|
if f.DOBTo != nil && *f.DOBTo != "" {
|
||||||
|
query += " AND u.birth_date <= ?"
|
||||||
|
args = append(args, *f.DOBTo)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sex
|
||||||
|
if f.Sex != nil && *f.Sex != "" {
|
||||||
|
query += " AND u.sex = ?"
|
||||||
|
args = append(args, *f.Sex)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Nationality
|
||||||
|
if f.Nationality != "" {
|
||||||
|
query += " AND um.nationality = ?"
|
||||||
|
args = append(args, f.Nationality)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Address
|
||||||
|
if f.AddressState != 0 {
|
||||||
|
query += " AND um.addressState = ?"
|
||||||
|
args = append(args, f.AddressState)
|
||||||
|
}
|
||||||
|
if f.AddressCity != 0 {
|
||||||
|
query += " AND um.addressCity = ?"
|
||||||
|
args = append(args, f.AddressCity)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Search
|
||||||
|
if f.Search != nil && *f.Search != "" {
|
||||||
|
like := "%" + *f.Search + "%"
|
||||||
|
query += `
|
||||||
|
AND (
|
||||||
|
um.fName LIKE ? OR
|
||||||
|
um.mName LIKE ? OR
|
||||||
|
um.spouseName LIKE ? OR
|
||||||
|
um.phone LIKE ? OR
|
||||||
|
um.mobile LIKE ?
|
||||||
|
)
|
||||||
|
`
|
||||||
|
args = append(args, like, like, like, like, like)
|
||||||
|
}
|
||||||
|
|
||||||
|
var count int
|
||||||
|
|
||||||
|
err = tx.QueryRowContext(ctx, query, args...).Scan(&count)
|
||||||
|
if err != nil {
|
||||||
|
return 0, fmt.Errorf("%s: query error: %w", Op, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return count, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (db *DataBase) SummaryByCity(ctx context.Context, provinceID uint, f analytic.PatientMapFilter) (map[uint][]entity.MapSummaryItem, error) {
|
func (db *DataBase) SummaryByCity(ctx context.Context, provinceID uint, f analytic.PatientMapFilter) (map[uint][]entity.MapSummaryItem, error) {
|
||||||
|
const Op = "repository.mysql.patient.map_summary"
|
||||||
|
|
||||||
return nil, nil
|
tx, err := db.conn.Conn().BeginTx(ctx, nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, richerror.New(Op).WithErr(err)
|
||||||
|
}
|
||||||
|
defer tx.Rollback()
|
||||||
|
|
||||||
|
query := `
|
||||||
|
SELECT
|
||||||
|
um.addressCity AS city_id,
|
||||||
|
ANY_VALUE(um.lat) AS lat,
|
||||||
|
ANY_VALUE(um.lng) AS lng,
|
||||||
|
COUNT(*) AS user_count
|
||||||
|
FROM user_metas um
|
||||||
|
JOIN users u ON u.id = um.user_id
|
||||||
|
JOIN cities c ON c.id = um.addressCity
|
||||||
|
WHERE c.state_id = ?
|
||||||
|
`
|
||||||
|
|
||||||
|
args := []any{provinceID}
|
||||||
|
// Birthdate filters
|
||||||
|
if f.MinDOB != nil && *f.MinDOB != "" {
|
||||||
|
query += " AND u.birth_date >= ?"
|
||||||
|
args = append(args, *f.MinDOB)
|
||||||
|
}
|
||||||
|
if f.MaxDOB != nil && *f.MaxDOB != "" {
|
||||||
|
query += " AND u.birth_date <= ?"
|
||||||
|
args = append(args, *f.MaxDOB)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sex filter
|
||||||
|
if f.Sex != nil && *f.Sex != "" {
|
||||||
|
query += " AND u.sex = ?"
|
||||||
|
args = append(args, *f.Sex)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Search filter
|
||||||
|
if f.Search != nil && *f.Search != "" {
|
||||||
|
like := "%" + *f.Search + "%"
|
||||||
|
query += `
|
||||||
|
AND (
|
||||||
|
um.fName LIKE ? OR
|
||||||
|
um.mName LIKE ? OR
|
||||||
|
um.spouseName LIKE ? OR
|
||||||
|
um.phone LIKE ? OR
|
||||||
|
um.mobile LIKE ?
|
||||||
|
)
|
||||||
|
`
|
||||||
|
args = append(args, like, like, like, like, like)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Group by city
|
||||||
|
query += " GROUP BY um.addressCity"
|
||||||
|
|
||||||
|
rows, err := tx.QueryContext(ctx, query, args...)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("%s: query error: %w", Op, err)
|
||||||
|
}
|
||||||
|
defer rows.Close()
|
||||||
|
|
||||||
|
result := make(map[uint][]entity.MapSummaryItem)
|
||||||
|
|
||||||
|
for rows.Next() {
|
||||||
|
var item entity.MapSummaryItem
|
||||||
|
|
||||||
|
err := rows.Scan(
|
||||||
|
&item.ID,
|
||||||
|
&item.Latitude,
|
||||||
|
&item.Longitude,
|
||||||
|
&item.Count,
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("%s: scan error: %w", Op, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
result[item.ID] = append(result[item.ID], item)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := rows.Err(); err != nil {
|
||||||
|
return nil, fmt.Errorf("%s: rows error: %w", Op, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return result, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (db *DataBase) SummaryByProvince(ctx context.Context, f analytic.PatientMapFilter) (map[uint][]entity.MapSummaryItem, error) {
|
func (db *DataBase) SummaryByProvince(ctx context.Context, f analytic.PatientMapFilter) (map[uint][]entity.MapSummaryItem, error) {
|
||||||
|
|
||||||
return nil, nil
|
const Op = "repository.mysql.patient.summary_by_province"
|
||||||
|
|
||||||
|
tx, err := db.conn.Conn().BeginTx(ctx, nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, richerror.New(Op).WithErr(err)
|
||||||
|
}
|
||||||
|
defer tx.Rollback()
|
||||||
|
|
||||||
|
query := `
|
||||||
|
SELECT
|
||||||
|
c.state_id,
|
||||||
|
ANY_VALUE(c.lat) AS lat,
|
||||||
|
ANY_VALUE(c.lng) AS lng,
|
||||||
|
COUNT(*) AS total
|
||||||
|
FROM user_metas um
|
||||||
|
JOIN users u ON u.id = um.user_id
|
||||||
|
JOIN cities c ON c.id = um.addressCity
|
||||||
|
WHERE 1 = 1
|
||||||
|
`
|
||||||
|
args := []any{}
|
||||||
|
|
||||||
|
// Birthdate filters
|
||||||
|
if f.MinDOB != nil && *f.MinDOB != "" {
|
||||||
|
query += " AND u.birth_date >= ?"
|
||||||
|
args = append(args, *f.MinDOB)
|
||||||
|
}
|
||||||
|
if f.MaxDOB != nil && *f.MaxDOB != "" {
|
||||||
|
query += " AND u.birth_date <= ?"
|
||||||
|
args = append(args, *f.MaxDOB)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sex filter
|
||||||
|
if f.Sex != nil && *f.Sex != "" {
|
||||||
|
query += " AND u.sex = ?"
|
||||||
|
args = append(args, *f.Sex)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Search filter
|
||||||
|
if f.Search != nil && *f.Search != "" {
|
||||||
|
like := "%" + *f.Search + "%"
|
||||||
|
query += `
|
||||||
|
AND (
|
||||||
|
um.fName LIKE ? OR
|
||||||
|
um.mName LIKE ? OR
|
||||||
|
um.spouseName LIKE ? OR
|
||||||
|
um.phone LIKE ? OR
|
||||||
|
um.mobile LIKE ?
|
||||||
|
)
|
||||||
|
`
|
||||||
|
args = append(args, like, like, like, like, like)
|
||||||
|
}
|
||||||
|
|
||||||
|
query += " GROUP BY c.state_id"
|
||||||
|
|
||||||
|
rows, err := tx.QueryContext(ctx, query, args...)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("%s: query error: %w", Op, err)
|
||||||
|
}
|
||||||
|
defer rows.Close()
|
||||||
|
|
||||||
|
result := make(map[uint][]entity.MapSummaryItem)
|
||||||
|
|
||||||
|
for rows.Next() {
|
||||||
|
var item entity.MapSummaryItem
|
||||||
|
|
||||||
|
if err := rows.Scan(&item.ID, &item.Latitude, &item.Longitude, &item.Count); err != nil {
|
||||||
|
return nil, fmt.Errorf("%s: scan error: %w", Op, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
result[item.ID] = []entity.MapSummaryItem{item}
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := rows.Err(); err != nil {
|
||||||
|
return nil, fmt.Errorf("%s: rows error: %w", Op, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return result, nil
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,12 +6,12 @@ import (
|
||||||
|
|
||||||
type ListPatientAnalyticRequest struct {
|
type ListPatientAnalyticRequest struct {
|
||||||
// All fields are optional
|
// All fields are optional
|
||||||
MinAge *int `query:"minAge,omitempty"`
|
MinAge *int `query:"minAge,omitempty"`
|
||||||
MaxAge *int `query:"maxAge,omitempty"`
|
MaxAge *int `query:"maxAge,omitempty"`
|
||||||
Sex *entity.Sex `query:"sex,omitempty"`
|
Sex *string `query:"sex,omitempty"`
|
||||||
|
|
||||||
City *int64 `query:"city,omitempty"`
|
City *uint16 `query:"city,omitempty"`
|
||||||
Province *int64 `query:"province,omitempty"`
|
Province *uint16 `query:"province,omitempty"`
|
||||||
|
|
||||||
Search *string `query:"search,omitempty"`
|
Search *string `query:"search,omitempty"`
|
||||||
|
|
||||||
|
|
@ -19,11 +19,11 @@ type ListPatientAnalyticRequest struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
type PatientAnalyticItem struct {
|
type PatientAnalyticItem struct {
|
||||||
ID int64 `json:"id"`
|
ID uint64 `json:"id"`
|
||||||
FirstName string `json:"first_name"`
|
FirstName string `json:"first_name"`
|
||||||
LastName string `json:"Last_name"`
|
LastName string `json:"Last_name"`
|
||||||
DateOfBirth string `json:"dob,omitempty"`
|
DateOfBirth string `json:"dob,omitempty"`
|
||||||
Sex entity.Sex `json:"sex"`
|
Sex string `json:"sex"`
|
||||||
Phone string `json:"phone"`
|
Phone string `json:"phone"`
|
||||||
Address entity.Address `json:"address"`
|
Address entity.Address `json:"address"`
|
||||||
}
|
}
|
||||||
|
|
@ -33,17 +33,17 @@ type PatientAnalyticResponse struct {
|
||||||
Total int `json:"total"`
|
Total int `json:"total"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func ToPatientResponse(patient entity.Patient) PatientAnalyticItem {
|
func ToPatientResponse(patient entity.UserMeta) PatientAnalyticItem {
|
||||||
return PatientAnalyticItem{
|
return PatientAnalyticItem{
|
||||||
ID: patient.ID,
|
ID: patient.ID,
|
||||||
FirstName: patient.FirstName,
|
FirstName: patient.Name,
|
||||||
LastName: patient.LastName,
|
LastName: patient.LastName,
|
||||||
DateOfBirth: patient.DateOfBirth,
|
DateOfBirth: patient.BirthDate,
|
||||||
Sex: patient.Sex,
|
Sex: patient.Gender,
|
||||||
Phone: patient.Phone,
|
Phone: *patient.Mobile,
|
||||||
Address: entity.Address{
|
Address: entity.Address{
|
||||||
ProvinceID: patient.Address.ProvinceID,
|
ProvinceID: patient.AddressState,
|
||||||
CityID: patient.Address.CityID,
|
CityID: patient.AddressCity,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -7,11 +7,11 @@ import (
|
||||||
type PatientFilter struct {
|
type PatientFilter struct {
|
||||||
DOBFrom *string // born after
|
DOBFrom *string // born after
|
||||||
DOBTo *string // born before
|
DOBTo *string // born before
|
||||||
Sex *entity.Sex
|
Sex *string
|
||||||
|
|
||||||
City *int64
|
Nationality string
|
||||||
Province *int64
|
AddressState uint16
|
||||||
Country *int64
|
AddressCity uint16
|
||||||
|
|
||||||
Search *string
|
Search *string
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,7 @@ var (
|
||||||
)
|
)
|
||||||
|
|
||||||
type Repository interface {
|
type Repository interface {
|
||||||
GetPatients(ctx context.Context, f PatientFilter) ([]entity.Patient, error)
|
GetPatients(ctx context.Context, f PatientFilter) ([]entity.UserMeta, error)
|
||||||
CountPatients(ctx context.Context, f PatientFilter) (int, error)
|
CountPatients(ctx context.Context, f PatientFilter) (int, error)
|
||||||
|
|
||||||
SummaryByCity(ctx context.Context, provinceID uint, f PatientMapFilter) (map[uint][]entity.MapSummaryItem, error)
|
SummaryByCity(ctx context.Context, provinceID uint, f PatientMapFilter) (map[uint][]entity.MapSummaryItem, error)
|
||||||
|
|
@ -41,14 +41,14 @@ func (s Service) List(ctx context.Context, req ListPatientAnalyticRequest) (Pati
|
||||||
dobFrom, dobTo := ageRangeToDOB(req.MinAge, req.MaxAge, time.Now())
|
dobFrom, dobTo := ageRangeToDOB(req.MinAge, req.MaxAge, time.Now())
|
||||||
|
|
||||||
filter := PatientFilter{
|
filter := PatientFilter{
|
||||||
DOBFrom: dobFrom,
|
DOBFrom: dobFrom,
|
||||||
DOBTo: dobTo,
|
DOBTo: dobTo,
|
||||||
Sex: req.Sex,
|
Sex: req.Sex,
|
||||||
City: req.City,
|
AddressCity: *req.City,
|
||||||
Province: req.Province,
|
AddressState: *req.Province,
|
||||||
Search: req.Search,
|
Search: req.Search,
|
||||||
Limit: limit,
|
Limit: limit,
|
||||||
Offset: offset,
|
Offset: offset,
|
||||||
}
|
}
|
||||||
|
|
||||||
items, err := s.repository.GetPatients(ctx, filter)
|
items, err := s.repository.GetPatients(ctx, filter)
|
||||||
|
|
|
||||||
|
|
@ -7,8 +7,8 @@ type Address struct {
|
||||||
Name string
|
Name string
|
||||||
Lat float64
|
Lat float64
|
||||||
Lon float64
|
Lon float64
|
||||||
CityID uint
|
CityID uint16
|
||||||
ProvinceID uint
|
ProvinceID uint16
|
||||||
}
|
}
|
||||||
|
|
||||||
type AddressAggregated struct {
|
type AddressAggregated struct {
|
||||||
|
|
|
||||||
|
|
@ -9,9 +9,8 @@ const (
|
||||||
)
|
)
|
||||||
|
|
||||||
type MapSummaryItem struct {
|
type MapSummaryItem struct {
|
||||||
LocationID int64
|
ID uint `json:"id"` // city_id OR state_id
|
||||||
Name string
|
Latitude float64 `json:"latitude"`
|
||||||
Count int
|
Longitude float64 `json:"longitude"`
|
||||||
CentroidLat float64
|
Count int `json:"count"`
|
||||||
CentroidLng float64
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,7 @@
|
||||||
package entity
|
package entity
|
||||||
|
|
||||||
|
import "time"
|
||||||
|
|
||||||
type Patient struct {
|
type Patient struct {
|
||||||
ID int64
|
ID int64
|
||||||
FirstName string
|
FirstName string
|
||||||
|
|
@ -15,6 +17,27 @@ type Patient struct {
|
||||||
EndDate string
|
EndDate string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type UserMeta struct {
|
||||||
|
ID uint64 `db:"id"`
|
||||||
|
UserID uint64 `db:"user_id"`
|
||||||
|
Name string `db:"name"`
|
||||||
|
LastName string `db:"last_name"`
|
||||||
|
Gender string `db:"gender"`
|
||||||
|
BirthDate string `db:"birth_date"`
|
||||||
|
BirthPlaceState uint16 `db:"birthPlaceState"`
|
||||||
|
BirthPlaceCity uint16 `db:"birthPlaceCity"`
|
||||||
|
Religion *string `db:"religion"`
|
||||||
|
Nationality *string `db:"nationality"`
|
||||||
|
AddressState uint16 `db:"addressState"`
|
||||||
|
AddressCity uint16 `db:"addressCity"`
|
||||||
|
Address string `db:"address"`
|
||||||
|
Mobile *string `db:"mobile"`
|
||||||
|
SpouseName *string `db:"spouseName"`
|
||||||
|
SpouseAlive *bool `db:"spouseAlive"`
|
||||||
|
CreatedAt *time.Time `db:"created_at"`
|
||||||
|
UpdatedAt *time.Time `db:"updated_at"`
|
||||||
|
}
|
||||||
|
|
||||||
// Sex ================================== Sex type ==========================================
|
// Sex ================================== Sex type ==========================================
|
||||||
type Sex string
|
type Sex string
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3,9 +3,9 @@ package purchaseapp
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
purchaseMysql "git.gocasts.ir/ebhomengo/niki/domain/purchase/repository/mysql"
|
||||||
purchaseHTTP "git.gocasts.ir/ebhomengo/niki/purchaseapp/delivery/http"
|
purchaseHTTP "git.gocasts.ir/ebhomengo/niki/purchaseapp/delivery/http"
|
||||||
purchaseHandler "git.gocasts.ir/ebhomengo/niki/purchaseapp/delivery/http/order"
|
purchaseHandler "git.gocasts.ir/ebhomengo/niki/purchaseapp/delivery/http/order"
|
||||||
purchaseMysql "git.gocasts.ir/ebhomengo/niki/purchaseapp/repository/mysql"
|
|
||||||
purchaseService "git.gocasts.ir/ebhomengo/niki/purchaseapp/service/order"
|
purchaseService "git.gocasts.ir/ebhomengo/niki/purchaseapp/service/order"
|
||||||
"git.gocasts.ir/ebhomengo/niki/repository/mysql"
|
"git.gocasts.ir/ebhomengo/niki/repository/mysql"
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,9 @@
|
||||||
package order
|
package order
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
entity "git.gocasts.ir/ebhomengo/niki/domain/order/entity"
|
||||||
|
order "git.gocasts.ir/ebhomengo/niki/domain/order/service"
|
||||||
richerror "git.gocasts.ir/ebhomengo/niki/pkg/rich_error"
|
richerror "git.gocasts.ir/ebhomengo/niki/pkg/rich_error"
|
||||||
"git.gocasts.ir/ebhomengo/niki/purchaseapp/entity"
|
|
||||||
"git.gocasts.ir/ebhomengo/niki/purchaseapp/service/order"
|
|
||||||
"github.com/labstack/echo/v4"
|
"github.com/labstack/echo/v4"
|
||||||
"net/http"
|
"net/http"
|
||||||
"time"
|
"time"
|
||||||
|
|
@ -18,7 +18,7 @@ func New(orderSvc order.Service) *Handler {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *Handler) CreateOrderHandler(c echo.Context) error {
|
func (h *Handler) CreateOrderHandler(c echo.Context) error {
|
||||||
var req order.CreateOrderRequest
|
var req CreateOrderRequest
|
||||||
if err := c.Bind(&req); err != nil {
|
if err := c.Bind(&req); err != nil {
|
||||||
msg, code := getErrorDataFromRichError(err)
|
msg, code := getErrorDataFromRichError(err)
|
||||||
return echo.NewHTTPError(code, msg)
|
return echo.NewHTTPError(code, msg)
|
||||||
|
|
@ -34,7 +34,7 @@ func (h *Handler) CreateOrderHandler(c echo.Context) error {
|
||||||
PaymentMethod: req.PaymentMethod,
|
PaymentMethod: req.PaymentMethod,
|
||||||
ProcessStatus: entity.WaitingToPay,
|
ProcessStatus: entity.WaitingToPay,
|
||||||
PaymentStatus: entity.UnPaid,
|
PaymentStatus: entity.UnPaid,
|
||||||
Address: req.Address,
|
AddressID: req.AddressID,
|
||||||
CreatedAt: time.Now(),
|
CreatedAt: time.Now(),
|
||||||
UpdatedAt: time.Now(),
|
UpdatedAt: time.Now(),
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,13 @@
|
||||||
package order
|
package order
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"git.gocasts.ir/ebhomengo/niki/purchaseapp/entity"
|
"git.gocasts.ir/ebhomengo/niki/domain/order/entity"
|
||||||
"git.gocasts.ir/ebhomengo/niki/types"
|
"git.gocasts.ir/ebhomengo/niki/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
type CreateOrderRequest struct {
|
type CreateOrderRequest struct {
|
||||||
UserID types.ID `json:"user_id"`
|
UserID types.ID `json:"user_id"`
|
||||||
Address string `json:"address"`
|
AddressID types.ID `json:"address_id"`
|
||||||
ShippingID types.ID `json:"shipping_id"`
|
ShippingID types.ID `json:"shipping_id"`
|
||||||
PaymentMethod entity.PaymentMethod `json:"payment_method"`
|
PaymentMethod entity.PaymentMethod `json:"payment_method"`
|
||||||
TotalAmount types.Price `json:"total_amount"`
|
TotalAmount types.Price `json:"total_amount"`
|
||||||
|
|
@ -4,5 +4,4 @@ import "github.com/labstack/echo/v4"
|
||||||
|
|
||||||
func (h Handler) SetRoutes(e *echo.Echo) {
|
func (h Handler) SetRoutes(e *echo.Echo) {
|
||||||
|
|
||||||
e.POST("/order/create", h.CreateOrderHandler)
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,19 +1,19 @@
|
||||||
package http
|
package http
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"git.gocasts.ir/ebhomengo/niki/purchaseapp/delivery/http/order"
|
order "git.gocasts.ir/ebhomengo/niki/domain/order/service"
|
||||||
orderService "git.gocasts.ir/ebhomengo/niki/purchaseapp/service/order"
|
orderHandler "git.gocasts.ir/ebhomengo/niki/purchaseapp/delivery/http/order"
|
||||||
"github.com/labstack/echo/v4"
|
"github.com/labstack/echo/v4"
|
||||||
"github.com/labstack/echo/v4/middleware"
|
"github.com/labstack/echo/v4/middleware"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Server struct {
|
type Server struct {
|
||||||
OrderHandler *order.Handler
|
OrderHandler *orderHandler.Handler
|
||||||
}
|
}
|
||||||
|
|
||||||
func New(orderSvc orderService.Service) *Server {
|
func New(orderSvc order.Service) *Server {
|
||||||
return &Server{
|
return &Server{
|
||||||
OrderHandler: order.New(orderSvc),
|
OrderHandler: orderHandler.New(orderSvc),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,59 +0,0 @@
|
||||||
package entity
|
|
||||||
|
|
||||||
import (
|
|
||||||
"git.gocasts.ir/ebhomengo/niki/types"
|
|
||||||
"time"
|
|
||||||
)
|
|
||||||
|
|
||||||
type Order struct {
|
|
||||||
ID types.ID
|
|
||||||
UserID types.ID
|
|
||||||
TotalAmount types.Price
|
|
||||||
TotalDiscount types.Price
|
|
||||||
ShippingID types.ID
|
|
||||||
PaymentMethod PaymentMethod
|
|
||||||
ProcessStatus ProcessStatus
|
|
||||||
PaymentStatus PaymentStatus
|
|
||||||
Address string
|
|
||||||
CreatedAt time.Time
|
|
||||||
UpdatedAt time.Time
|
|
||||||
}
|
|
||||||
|
|
||||||
type OrderItem struct {
|
|
||||||
ID types.ID
|
|
||||||
ProductID types.ID
|
|
||||||
Price types.Price
|
|
||||||
Quantity types.Count
|
|
||||||
PriceWithDiscount types.Price
|
|
||||||
OrderID types.ID
|
|
||||||
CreatedAt time.Time
|
|
||||||
}
|
|
||||||
|
|
||||||
type PaymentMethod string
|
|
||||||
|
|
||||||
const (
|
|
||||||
Online PaymentMethod = "online"
|
|
||||||
Wallet = "wallet"
|
|
||||||
Cart = "cart"
|
|
||||||
)
|
|
||||||
|
|
||||||
type ProcessStatus string
|
|
||||||
|
|
||||||
const (
|
|
||||||
WaitingToPay ProcessStatus = "waiting-to-pay"
|
|
||||||
processing = "processing"
|
|
||||||
accepted = "accepted"
|
|
||||||
preparing = "preparing"
|
|
||||||
prepared = "prepared"
|
|
||||||
givenToPost = "given-to-post"
|
|
||||||
delivered = "delivered"
|
|
||||||
cancelled = "cancelled"
|
|
||||||
)
|
|
||||||
|
|
||||||
type PaymentStatus string
|
|
||||||
|
|
||||||
const (
|
|
||||||
Paid PaymentStatus = "paid"
|
|
||||||
UnPaid = "unpaid"
|
|
||||||
Cancelled = "cancelled"
|
|
||||||
)
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
package mysql
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
package order
|
|
||||||
Loading…
Reference in New Issue