diff --git a/app/delivery/web/api/restricted/addresses.go b/app/delivery/web/api/restricted/addresses.go new file mode 100644 index 0000000..903f011 --- /dev/null +++ b/app/delivery/web/api/restricted/addresses.go @@ -0,0 +1,157 @@ +package restricted + +import ( + "strconv" + + "git.ma-al.com/goc_daniel/b2b/app/service/addressesService" + "git.ma-al.com/goc_daniel/b2b/app/utils/i18n" + "git.ma-al.com/goc_daniel/b2b/app/utils/localeExtractor" + "git.ma-al.com/goc_daniel/b2b/app/utils/nullable" + "git.ma-al.com/goc_daniel/b2b/app/utils/response" + "git.ma-al.com/goc_daniel/b2b/app/utils/responseErrors" + "github.com/gofiber/fiber/v3" +) + +type AddressesHandler struct { + addressesService *addressesService.AddressesService +} + +func NewAddressesHandler() *AddressesHandler { + addressesService := addressesService.New() + return &AddressesHandler{ + addressesService: addressesService, + } +} + +func AddressesHandlerRoutes(r fiber.Router) fiber.Router { + handler := NewAddressesHandler() + + r.Get("/get-template", handler.GetTemplate) + r.Post("/add-new-address", handler.AddNewAddress) + r.Post("/modify-address", handler.ModifyAddress) + r.Get("/retrieve-addresses", handler.RetrieveAddressesInfo) + r.Delete("/delete-address", handler.DeleteAddress) + + return r +} + +func (h *AddressesHandler) GetTemplate(c fiber.Ctx) error { + country_id_attribute := c.Query("country_id") + country_id, err := strconv.Atoi(country_id_attribute) + if err != nil { + return c.Status(responseErrors.GetErrorStatus(responseErrors.ErrBadAttribute)). + JSON(response.Make(nullable.GetNil(""), 0, responseErrors.GetErrorCode(c, responseErrors.ErrBadAttribute))) + } + + template, err := h.addressesService.GetTemplate(uint(country_id)) + if err != nil { + return c.Status(responseErrors.GetErrorStatus(err)). + JSON(response.Make(nullable.GetNil(""), 0, responseErrors.GetErrorCode(c, err))) + } + + return c.JSON(response.Make(&template, 0, i18n.T_(c, response.Message_OK))) +} + +func (h *AddressesHandler) AddNewAddress(c fiber.Ctx) error { + userID, ok := localeExtractor.GetUserID(c) + if !ok { + return c.Status(responseErrors.GetErrorStatus(responseErrors.ErrInvalidBody)). + JSON(response.Make(nullable.GetNil(""), 0, responseErrors.GetErrorCode(c, responseErrors.ErrInvalidBody))) + } + + address_info := string(c.Body()) + if address_info == "" { + return c.Status(responseErrors.GetErrorStatus(responseErrors.ErrInvalidBody)). + JSON(response.Make(nullable.GetNil(""), 0, responseErrors.GetErrorCode(c, responseErrors.ErrInvalidBody))) + } + + country_id_attribute := c.Query("country_id") + country_id, err := strconv.Atoi(country_id_attribute) + if err != nil { + return c.Status(responseErrors.GetErrorStatus(responseErrors.ErrBadAttribute)). + JSON(response.Make(nullable.GetNil(""), 0, responseErrors.GetErrorCode(c, responseErrors.ErrBadAttribute))) + } + + err = h.addressesService.AddNewAddress(userID, address_info, uint(country_id)) + if err != nil { + return c.Status(responseErrors.GetErrorStatus(err)). + JSON(response.Make(nullable.GetNil(""), 0, responseErrors.GetErrorCode(c, err))) + } + + return c.JSON(response.Make(nullable.GetNil(""), 0, i18n.T_(c, response.Message_OK))) +} + +func (h *AddressesHandler) ModifyAddress(c fiber.Ctx) error { + userID, ok := localeExtractor.GetUserID(c) + if !ok { + return c.Status(responseErrors.GetErrorStatus(responseErrors.ErrInvalidBody)). + JSON(response.Make(nullable.GetNil(""), 0, responseErrors.GetErrorCode(c, responseErrors.ErrInvalidBody))) + } + + address_id_attribute := c.Query("address_id") + address_id, err := strconv.Atoi(address_id_attribute) + if err != nil { + return c.Status(responseErrors.GetErrorStatus(responseErrors.ErrBadAttribute)). + JSON(response.Make(nullable.GetNil(""), 0, responseErrors.GetErrorCode(c, responseErrors.ErrBadAttribute))) + } + + address_info := string(c.Body()) + if address_info == "" { + return c.Status(responseErrors.GetErrorStatus(responseErrors.ErrInvalidBody)). + JSON(response.Make(nullable.GetNil(""), 0, responseErrors.GetErrorCode(c, responseErrors.ErrInvalidBody))) + } + + country_id_attribute := c.Query("country_id") + country_id, err := strconv.Atoi(country_id_attribute) + if err != nil { + return c.Status(responseErrors.GetErrorStatus(responseErrors.ErrBadAttribute)). + JSON(response.Make(nullable.GetNil(""), 0, responseErrors.GetErrorCode(c, responseErrors.ErrBadAttribute))) + } + + err = h.addressesService.ModifyAddress(userID, uint(address_id), address_info, uint(country_id)) + if err != nil { + return c.Status(responseErrors.GetErrorStatus(err)). + JSON(response.Make(nullable.GetNil(""), 0, responseErrors.GetErrorCode(c, err))) + } + + return c.JSON(response.Make(nullable.GetNil(""), 0, i18n.T_(c, response.Message_OK))) +} + +func (h *AddressesHandler) RetrieveAddressesInfo(c fiber.Ctx) error { + userID, ok := localeExtractor.GetUserID(c) + if !ok { + return c.Status(responseErrors.GetErrorStatus(responseErrors.ErrInvalidBody)). + JSON(response.Make(nullable.GetNil(""), 0, responseErrors.GetErrorCode(c, responseErrors.ErrInvalidBody))) + } + + addresses_info, err := h.addressesService.RetrieveAddressesInfo(userID) + if err != nil { + return c.Status(responseErrors.GetErrorStatus(err)). + JSON(response.Make(nullable.GetNil(""), 0, responseErrors.GetErrorCode(c, err))) + } + + return c.JSON(response.Make(&addresses_info, 0, i18n.T_(c, response.Message_OK))) +} + +func (h *AddressesHandler) DeleteAddress(c fiber.Ctx) error { + userID, ok := localeExtractor.GetUserID(c) + if !ok { + return c.Status(responseErrors.GetErrorStatus(responseErrors.ErrInvalidBody)). + JSON(response.Make(nullable.GetNil(""), 0, responseErrors.GetErrorCode(c, responseErrors.ErrInvalidBody))) + } + + address_id_attribute := c.Query("address_id") + address_id, err := strconv.Atoi(address_id_attribute) + if err != nil { + return c.Status(responseErrors.GetErrorStatus(responseErrors.ErrBadAttribute)). + JSON(response.Make(nullable.GetNil(""), 0, responseErrors.GetErrorCode(c, responseErrors.ErrBadAttribute))) + } + + err = h.addressesService.DeleteAddress(userID, uint(address_id)) + if err != nil { + return c.Status(responseErrors.GetErrorStatus(err)). + JSON(response.Make(nullable.GetNil(""), 0, responseErrors.GetErrorCode(c, err))) + } + + return c.JSON(response.Make(nullable.GetNil(""), 0, i18n.T_(c, response.Message_OK))) +} diff --git a/app/delivery/web/init.go b/app/delivery/web/init.go index 51d9f51..2162d66 100644 --- a/app/delivery/web/init.go +++ b/app/delivery/web/init.go @@ -132,6 +132,10 @@ func (s *Server) Setup() error { carts := s.restricted.Group("/carts") restricted.CartsHandlerRoutes(carts) + // addresses (restricted) + addresses := s.restricted.Group("/addresses") + restricted.AddressesHandlerRoutes(addresses) + // storage (uses various authorization means) restrictedStorage := s.restricted.Group("/storage") webdavStorage := s.webdav.Group("/storage") diff --git a/app/model/address.go b/app/model/address.go new file mode 100644 index 0000000..a84056a --- /dev/null +++ b/app/model/address.go @@ -0,0 +1,79 @@ +package model + +type Address struct { + ID uint `gorm:"column:id;primaryKey;autoIncrement" json:"id"` + CustomerID uint `gorm:"column:b2b_customer_id;not null;index" json:"customer_id"` + AddressInfo string `gorm:"column:address_info;not null" json:"address_info"` + CountryID uint `gorm:"column:b2b_country_id;not null" json:"country_id"` +} + +func (Address) TableName() string { + return "b2b_addresses" +} + +type AddressUnparsed struct { + ID uint `gorm:"column:id;primaryKey;autoIncrement" json:"id"` + CustomerID uint `gorm:"column:b2b_customer_id;not null;index" json:"customer_id"` + AddressInfo AddressField `gorm:"column:address_info;not null" json:"address_info"` + CountryID uint `gorm:"column:b2b_country_id;not null" json:"country_id"` +} + +type AddressField interface { +} + +// Address template in Poland +type AddressPL struct { + PostalCode string `json:"postal_code"` // format: 00-000 + City string `json:"city"` // e.g. Kraków + Voivodeship string `json:"voivodeship"` // e.g. małopolskie (optional but useful) + + Street string `json:"street"` // e.g. Marszałkowska + BuildingNo string `json:"building_no"` // e.g. 10, 221B, 12A + ApartmentNo string `json:"apartment_no"` // e.g. 5, 12B + + AddressLine2 string `json:"address_line2"` // optional extra info + + Recipient string `json:"recipient"` // name/company +} + +// Address template in Great Britain +type AddressGB struct { + PostalCode string `json:"postal_code"` // e.g. SW1A 1AA + PostTown string `json:"post_town"` // e.g. London + County string `json:"county"` // optional + + Thoroughfare string `json:"thoroughfare"` // street name, e.g. Baker Street + BuildingNo string `json:"building_no"` // e.g. 221B + BuildingName string `json:"building_name"` // e.g. Flatiron House + SubBuilding string `json:"sub_building"` // e.g. Flat 5, Apt 2 + + AddressLine2 string `json:"address_line2"` + Recipient string `json:"recipient"` +} + +// Address template in Czech Republic +type AddressCZ struct { + PostalCode string `json:"postal_code"` // usually 110 00 or 11000 + City string `json:"city"` // e.g. Praha + Region string `json:"region"` + + Street string `json:"street"` // may be omitted in some village-style addresses + HouseNumber string `json:"house_number"` // descriptive / conscription no. + OrientationNumber string `json:"orientation_number"` // optional, often after slash + + AddressLine2 string `json:"address_line2"` + Recipient string `json:"recipient"` +} + +// Address template in Germany +type AddressDE struct { + PostalCode string `json:"postal_code"` // e.g. 10115 + City string `json:"city"` // e.g. Berlin + State string `json:"state"` // Bundesland, optional + + Street string `json:"street"` // e.g. Unter den Linden + HouseNumber string `json:"house_number"` // e.g. 77, 12a + + AddressLine2 string `json:"address_line2"` // extra details + Recipient string `json:"recipient"` +} diff --git a/app/repos/addressesRepo/addressesRepo.go b/app/repos/addressesRepo/addressesRepo.go new file mode 100644 index 0000000..5f674a0 --- /dev/null +++ b/app/repos/addressesRepo/addressesRepo.go @@ -0,0 +1,91 @@ +package addressesRepo + +import ( + "git.ma-al.com/goc_daniel/b2b/app/db" + "git.ma-al.com/goc_daniel/b2b/app/model" +) + +type UIAddressesRepo interface { + UserHasAddress(user_id uint, address_id uint) (uint, error) + UserAddressesAmt(user_id uint) (uint, error) + AddNewAddress(user_id uint, address_info string, country_id uint) error + UpdateAddress(user_id uint, address_id uint, address_info string, country_id uint) error + RetrieveAddresses(user_id uint) (*[]model.Address, error) + DeleteAddress(user_id uint, address_id uint) error +} + +type AddressesRepo struct{} + +func New() UIAddressesRepo { + return &AddressesRepo{} +} + +func (repo *AddressesRepo) UserHasAddress(user_id uint, address_id uint) (uint, error) { + var amt uint + + err := db.DB. + Table("b2b_addresses"). + Select("COUNT(*) AS amt"). + Where("id = ? AND b2b_customer_id = ?", address_id, user_id). + Scan(&amt). + Error + + return amt, err +} + +func (repo *AddressesRepo) UserAddressesAmt(user_id uint) (uint, error) { + var amt uint + + err := db.DB. + Table("b2b_addresses"). + Select("COUNT(*) AS amt"). + Where("b2b_customer_id = ?", user_id). + Scan(&amt). + Error + + return amt, err +} + +func (repo *AddressesRepo) AddNewAddress(user_id uint, address_info string, country_id uint) error { + address := model.Address{ + CustomerID: user_id, + AddressInfo: address_info, + CountryID: country_id, + } + + return db.DB. + Create(&address). + Error +} + +func (repo *AddressesRepo) UpdateAddress(user_id uint, address_id uint, address_info string, country_id uint) error { + address := model.Address{ + ID: address_id, + CustomerID: user_id, + AddressInfo: address_info, + CountryID: country_id, + } + + return db.DB. + Where("id = ? AND b2b_customer_id = ?", address_id, user_id). + Updates(&address). + Error +} + +func (repo *AddressesRepo) RetrieveAddresses(user_id uint) (*[]model.Address, error) { + var addresses []model.Address + + err := db.DB. + Where("b2b_customer_id = ?", user_id). + Find(&addresses). + Error + + return &addresses, err +} + +func (repo *AddressesRepo) DeleteAddress(user_id uint, address_id uint) error { + return db.DB. + Where("id = ? AND b2b_customer_id = ?", address_id, user_id). + Delete(&model.Address{}). + Error +} diff --git a/app/service/addressesService/addressesService.go b/app/service/addressesService/addressesService.go new file mode 100644 index 0000000..b077486 --- /dev/null +++ b/app/service/addressesService/addressesService.go @@ -0,0 +1,152 @@ +package addressesService + +import ( + "encoding/json" + "fmt" + "strings" + + "git.ma-al.com/goc_daniel/b2b/app/model" + "git.ma-al.com/goc_daniel/b2b/app/repos/addressesRepo" + constdata "git.ma-al.com/goc_daniel/b2b/app/utils/const_data" + "git.ma-al.com/goc_daniel/b2b/app/utils/responseErrors" +) + +type AddressesService struct { + repo addressesRepo.UIAddressesRepo +} + +func New() *AddressesService { + return &AddressesService{ + repo: addressesRepo.New(), + } +} + +func (s *AddressesService) GetTemplate(country_id uint) (model.AddressField, error) { + switch country_id { + + case 1: // Poland + return model.AddressPL{}, nil + + case 2: // Great Britain + return model.AddressGB{}, nil + + case 3: // Czech Republic + return model.AddressCZ{}, nil + + case 4: // Germany + return model.AddressDE{}, nil + + default: + return nil, responseErrors.ErrInvalidCountryID + } +} + +func (s *AddressesService) AddNewAddress(user_id uint, address_info string, country_id uint) error { + amt, err := s.repo.UserAddressesAmt(user_id) + if err != nil { + return err + } else if amt >= constdata.MAX_AMOUNT_OF_ADDRESSES_PER_USER { + return responseErrors.ErrMaxAmtOfAddressesReached + } + + _, err = s.validateAddressJson(address_info, country_id) + if err != nil { + return err + } + + return s.repo.AddNewAddress(user_id, address_info, country_id) +} + +// country_id = 0 means that country_id remains unchanged +func (s *AddressesService) ModifyAddress(user_id uint, address_id uint, address_info string, country_id uint) error { + amt, err := s.repo.UserHasAddress(user_id, address_id) + if err != nil { + return err + } else if amt != 1 { + return responseErrors.ErrUserHasNoSuchAddress + } + + _, err = s.validateAddressJson(address_info, country_id) + if err != nil { + return err + } + + return s.repo.UpdateAddress(user_id, address_id, address_info, country_id) +} + +func (s *AddressesService) RetrieveAddressesInfo(user_id uint) (*[]model.AddressUnparsed, error) { + parsed_addresses, err := s.repo.RetrieveAddresses(user_id) + if err != nil { + return nil, err + } + + var unparsed_addresses []model.AddressUnparsed + + for i := 0; i < len(*parsed_addresses); i++ { + var next_address model.AddressUnparsed + next_address.ID = (*parsed_addresses)[i].ID + next_address.CustomerID = (*parsed_addresses)[i].CustomerID + next_address.CountryID = (*parsed_addresses)[i].CountryID + + next_address.AddressInfo, err = s.validateAddressJson((*parsed_addresses)[i].AddressInfo, next_address.CountryID) + // log such errors + if err != nil { + fmt.Printf("err: %v\n", err) + } + + unparsed_addresses = append(unparsed_addresses, next_address) + } + + return &unparsed_addresses, nil +} + +func (s *AddressesService) DeleteAddress(user_id uint, address_id uint) error { + amt, err := s.repo.UserHasAddress(user_id, address_id) + if err != nil { + return err + } else if amt != 1 { + return responseErrors.ErrUserHasNoSuchAddress + } + + return s.repo.DeleteAddress(user_id, address_id) +} + +// validateAddressJson makes sure that the info string represents a valid json of address in given country +func (s *AddressesService) validateAddressJson(info string, country_id uint) (model.AddressField, error) { + dec := json.NewDecoder(strings.NewReader(info)) + dec.DisallowUnknownFields() + + switch country_id { + + case 1: // Poland + var address model.AddressPL + if err := dec.Decode(&address); err != nil { + return address, responseErrors.ErrInvalidAddressJSON + } + return address, nil + + case 2: // Great Britain + var address model.AddressGB + if err := dec.Decode(&address); err != nil { + return address, responseErrors.ErrInvalidAddressJSON + } + return address, nil + + case 3: // Czech Republic + var address model.AddressCZ + if err := dec.Decode(&address); err != nil { + return address, responseErrors.ErrInvalidAddressJSON + } + return address, nil + + case 4: // Germany + var address model.AddressDE + if err := dec.Decode(&address); err != nil { + return address, responseErrors.ErrInvalidAddressJSON + } + return address, nil + + default: + return nil, responseErrors.ErrInvalidCountryID + } +} diff --git a/app/utils/const_data/consts.go b/app/utils/const_data/consts.go index 1ed8a7c..aa62f27 100644 --- a/app/utils/const_data/consts.go +++ b/app/utils/const_data/consts.go @@ -12,6 +12,8 @@ const CATEGORY_TREE_ROOT_ID = 2 const MAX_AMOUNT_OF_CARTS_PER_USER = 10 const DEFAULT_NEW_CART_NAME = "new cart" +const MAX_AMOUNT_OF_ADDRESSES_PER_USER = 10 + const USER_LOCALE = "user" // WEBDAV diff --git a/app/utils/responseErrors/responseErrors.go b/app/utils/responseErrors/responseErrors.go index b3fe72f..28802e1 100644 --- a/app/utils/responseErrors/responseErrors.go +++ b/app/utils/responseErrors/responseErrors.go @@ -72,6 +72,12 @@ var ( // Typed errors for data parsing ErrJSONBody = errors.New("invalid JSON body") + + // Typed errors for addresses + ErrMaxAmtOfAddressesReached = errors.New("maximal amount of addresses per user reached") + ErrUserHasNoSuchAddress = errors.New("user has no such address") + ErrInvalidCountryID = errors.New("invalid country id") + ErrInvalidAddressJSON = errors.New("invalid address json") ) // Error represents an error with HTTP status code @@ -154,7 +160,7 @@ func GetErrorCode(c fiber.Ctx, err error) string { case errors.Is(err, ErrBadField): return i18n.T_(c, "error.err_bad_field") case errors.Is(err, ErrInvalidURLSlug): - return i18n.T_(c, "error.invalid_url_slug") + return i18n.T_(c, "error.err_invalid_url_slug") case errors.Is(err, ErrInvalidXHTML): return i18n.T_(c, "error.err_invalid_html") case errors.Is(err, ErrAIResponseFail): @@ -166,35 +172,44 @@ func GetErrorCode(c fiber.Ctx, err error) string { return i18n.T_(c, "error.err_bad_paging") case errors.Is(err, ErrNoRootFound): - return i18n.T_(c, "error.no_root_found") + return i18n.T_(c, "error.err_no_root_found") case errors.Is(err, ErrCircularDependency): - return i18n.T_(c, "error.circular_dependency") + return i18n.T_(c, "error.err_circular_dependency") case errors.Is(err, ErrStartCategoryNotFound): - return i18n.T_(c, "error.start_category_not_found") + return i18n.T_(c, "error.err_start_category_not_found") case errors.Is(err, ErrRootNeverReached): - return i18n.T_(c, "error.root_never_reached") + return i18n.T_(c, "error.err_root_never_reached") case errors.Is(err, ErrMaxAmtOfCartsReached): - return i18n.T_(c, "error.max_amt_of_carts_reached") + return i18n.T_(c, "error.err_max_amt_of_carts_reached") case errors.Is(err, ErrUserHasNoSuchCart): - return i18n.T_(c, "error.user_has_no_such_cart") + return i18n.T_(c, "error.err_user_has_no_such_cart") case errors.Is(err, ErrProductOrItsVariationDoesNotExist): - return i18n.T_(c, "error.product_or_its_variation_does_not_exist") + return i18n.T_(c, "error.err_product_or_its_variation_does_not_exist") case errors.Is(err, ErrAccessDenied): - return i18n.T_(c, "error.access_denied") + return i18n.T_(c, "error.err_access_denied") case errors.Is(err, ErrFolderDoesNotExist): - return i18n.T_(c, "error.folder_does_not_exist") + return i18n.T_(c, "error.err_folder_does_not_exist") case errors.Is(err, ErrFileDoesNotExist): - return i18n.T_(c, "error.file_does_not_exist") + return i18n.T_(c, "error.err_file_does_not_exist") case errors.Is(err, ErrNameTaken): - return i18n.T_(c, "error.name_taken") + return i18n.T_(c, "error.err_name_taken") case errors.Is(err, ErrMissingFileFieldDocument): - return i18n.T_(c, "error.missing_file_field_document") + return i18n.T_(c, "error.err_missing_file_field_document") case errors.Is(err, ErrJSONBody): return i18n.T_(c, "error.err_json_body") + case errors.Is(err, ErrMaxAmtOfAddressesReached): + return i18n.T_(c, "error.err_max_amt_of_addresses_reached") + case errors.Is(err, ErrUserHasNoSuchAddress): + return i18n.T_(c, "error.err_user_has_no_such_address") + case errors.Is(err, ErrInvalidCountryID): + return i18n.T_(c, "error.err_invalid_country_id") + case errors.Is(err, ErrInvalidAddressJSON): + return i18n.T_(c, "error.err_invalid_address_json") + default: return i18n.T_(c, "error.err_internal_server_error") } @@ -246,7 +261,11 @@ func GetErrorStatus(err error) int { errors.Is(err, ErrFileDoesNotExist), errors.Is(err, ErrNameTaken), errors.Is(err, ErrMissingFileFieldDocument), - errors.Is(err, ErrJSONBody): + errors.Is(err, ErrJSONBody), + errors.Is(err, ErrMaxAmtOfAddressesReached), + errors.Is(err, ErrUserHasNoSuchAddress), + errors.Is(err, ErrInvalidCountryID), + errors.Is(err, ErrInvalidAddressJSON): return fiber.StatusBadRequest case errors.Is(err, ErrEmailExists): return fiber.StatusConflict diff --git a/bo/components.d.ts b/bo/components.d.ts index 51b00ed..06b4ea1 100644 --- a/bo/components.d.ts +++ b/bo/components.d.ts @@ -13,7 +13,6 @@ declare module 'vue' { export interface GlobalComponents { CartDetails: typeof import('./src/components/customer/CartDetails.vue')['default'] CategoryMenu: typeof import('./src/components/inner/categoryMenu.vue')['default'] - CategoryMenuListing: typeof import('./src/components/inner/categoryMenuListing.vue')['default'] Cs_PrivacyPolicyView: typeof import('./src/components/terms/cs_PrivacyPolicyView.vue')['default'] Cs_TermsAndConditionsView: typeof import('./src/components/terms/cs_TermsAndConditionsView.vue')['default'] En_PrivacyPolicyView: typeof import('./src/components/terms/en_PrivacyPolicyView.vue')['default'] diff --git a/bruno/b2b_daniel/addresses/add-new-address.yml b/bruno/b2b_daniel/addresses/add-new-address.yml new file mode 100644 index 0000000..9c1abc1 --- /dev/null +++ b/bruno/b2b_daniel/addresses/add-new-address.yml @@ -0,0 +1,31 @@ +info: + name: add-new-address + type: http + seq: 1 + +http: + method: POST + url: http://localhost:3000/api/v1/restricted/addresses/add-new-address?country_id=1 + params: + - name: country_id + value: "1" + type: query + body: + type: json + data: |- + { + "postal_code": "31-154", + "city": "Kraków", + "voivodeship": "małopolskie", + "street": "Długa", + "building_no": "5", + "apartment_no": "7", + "recipient": "Jan Kowalski" + } + auth: inherit + +settings: + encodeUrl: true + timeout: 0 + followRedirects: true + maxRedirects: 5 diff --git a/bruno/b2b_daniel/addresses/delete-address.yml b/bruno/b2b_daniel/addresses/delete-address.yml new file mode 100644 index 0000000..dc9d33c --- /dev/null +++ b/bruno/b2b_daniel/addresses/delete-address.yml @@ -0,0 +1,19 @@ +info: + name: delete-address + type: http + seq: 4 + +http: + method: DELETE + url: http://localhost:3000/api/v1/restricted/addresses/delete-address?address_id=1 + params: + - name: address_id + value: "1" + type: query + auth: inherit + +settings: + encodeUrl: true + timeout: 0 + followRedirects: true + maxRedirects: 5 diff --git a/bruno/b2b_daniel/addresses/folder.yml b/bruno/b2b_daniel/addresses/folder.yml new file mode 100644 index 0000000..aaa37e8 --- /dev/null +++ b/bruno/b2b_daniel/addresses/folder.yml @@ -0,0 +1,7 @@ +info: + name: addresses + type: folder + seq: 10 + +request: + auth: inherit diff --git a/bruno/b2b_daniel/addresses/get-template.yml b/bruno/b2b_daniel/addresses/get-template.yml new file mode 100644 index 0000000..4105fb8 --- /dev/null +++ b/bruno/b2b_daniel/addresses/get-template.yml @@ -0,0 +1,19 @@ +info: + name: get-template + type: http + seq: 5 + +http: + method: GET + url: http://localhost:3000/api/v1/restricted/addresses/get-template?country_id=3 + params: + - name: country_id + value: "3" + type: query + auth: inherit + +settings: + encodeUrl: true + timeout: 0 + followRedirects: true + maxRedirects: 5 diff --git a/bruno/b2b_daniel/addresses/modify-address.yml b/bruno/b2b_daniel/addresses/modify-address.yml new file mode 100644 index 0000000..aadd02d --- /dev/null +++ b/bruno/b2b_daniel/addresses/modify-address.yml @@ -0,0 +1,33 @@ +info: + name: modify-address + type: http + seq: 2 + +http: + method: POST + url: http://localhost:3000/api/v1/restricted/addresses/modify-address?country_id=1&address_id=1 + params: + - name: country_id + value: "1" + type: query + - name: address_id + value: "1" + type: query + body: + type: json + data: |- + { + "postal_code": "31-154", + "city": "Kraków", + "voivodeship": "śląskie", + "street": "Długa", + "building_no": "5", + "recipient": "Adam Adamowicz" + } + auth: inherit + +settings: + encodeUrl: true + timeout: 0 + followRedirects: true + maxRedirects: 5 diff --git a/bruno/b2b_daniel/addresses/retrieve-addresses.yml b/bruno/b2b_daniel/addresses/retrieve-addresses.yml new file mode 100644 index 0000000..e490024 --- /dev/null +++ b/bruno/b2b_daniel/addresses/retrieve-addresses.yml @@ -0,0 +1,15 @@ +info: + name: retrieve-addresses + type: http + seq: 3 + +http: + method: GET + url: http://localhost:3000/api/v1/restricted/addresses/retrieve-addresses + auth: inherit + +settings: + encodeUrl: true + timeout: 0 + followRedirects: true + maxRedirects: 5 diff --git a/bruno/b2b_daniel/storage-restricted/download-file.yml b/bruno/b2b_daniel/storage-restricted/download-file.yml new file mode 100644 index 0000000..13553de --- /dev/null +++ b/bruno/b2b_daniel/storage-restricted/download-file.yml @@ -0,0 +1,15 @@ +info: + name: download-file + type: http + seq: 3 + +http: + method: GET + url: http://localhost:3000/api/v1/restricted/storage/download-file/dest/src/cccc.txt + auth: inherit + +settings: + encodeUrl: true + timeout: 0 + followRedirects: true + maxRedirects: 5 diff --git a/bruno/b2b_daniel/storage-restricted/list-content.yml b/bruno/b2b_daniel/storage-restricted/list-content.yml new file mode 100644 index 0000000..7c94250 --- /dev/null +++ b/bruno/b2b_daniel/storage-restricted/list-content.yml @@ -0,0 +1,15 @@ +info: + name: list-content + type: http + seq: 2 + +http: + method: GET + url: http://localhost:3000/api/v1/restricted/storage/list-content/dest/src + auth: inherit + +settings: + encodeUrl: true + timeout: 0 + followRedirects: true + maxRedirects: 5 diff --git a/i18n/migrations/20260302163122_create_tables.sql b/i18n/migrations/20260302163122_create_tables.sql index d975294..a82cea5 100644 --- a/i18n/migrations/20260302163122_create_tables.sql +++ b/i18n/migrations/20260302163122_create_tables.sql @@ -210,6 +210,18 @@ ON `b2b_countries` ( `ps_id_country` ASC ); +-- addresses +CREATE TABLE IF NOT EXISTS b2b_addresses ( + id BIGINT UNSIGNED AUTO_INCREMENT NOT NULL, + b2b_customer_id BIGINT UNSIGNED NOT NULL, + address_info TEXT NOT NULL, + b2b_country_id BIGINT UNSIGNED NOT NULL, + PRIMARY KEY (id), + CONSTRAINT fk_b2b_addresses_b2b_customers FOREIGN KEY (b2b_customer_id) REFERENCES b2b_customers (id) ON DELETE CASCADE ON UPDATE CASCADE, + CONSTRAINT fk_b2b_addresses_b2b_countries FOREIGN KEY (b2b_country_id) REFERENCES b2b_countries (id) ON DELETE CASCADE ON UPDATE CASCADE +) ENGINE = InnoDB; + + CREATE TABLE b2b_specific_price ( id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY, name VARCHAR(255) NOT NULL,