Compare commits
9 Commits
is_oem
...
9a90de3f11
| Author | SHA1 | Date | |
|---|---|---|---|
| 9a90de3f11 | |||
| 6efb39edf7 | |||
| e9af4bf311 | |||
| cc570cc6a8 | |||
| 1bf706dcd0 | |||
| e31ecda582 | |||
| 8e063978a8 | |||
| 31a2744131 | |||
| f55d59a0fd |
@@ -32,6 +32,7 @@ func CustomerHandlerRoutes(r fiber.Router) fiber.Router {
|
||||
|
||||
r.Get("", handler.customerData)
|
||||
r.Get("/list", middleware.Require(perms.UserReadAny), handler.listCustomers)
|
||||
r.Patch("/no-vat", middleware.Require(perms.UserWriteAny), handler.setCustomerNoVatStatus)
|
||||
return r
|
||||
}
|
||||
|
||||
@@ -100,3 +101,28 @@ var columnMappingListUsers map[string]string = map[string]string{
|
||||
"first_name": "users.first_name",
|
||||
"last_name": "users.last_name",
|
||||
}
|
||||
|
||||
func (h *customerHandler) setCustomerNoVatStatus(fc fiber.Ctx) error {
|
||||
user, ok := localeExtractor.GetCustomer(fc)
|
||||
if !ok || user == nil {
|
||||
return fc.Status(responseErrors.GetErrorStatus(responseErrors.ErrInvalidBody)).
|
||||
JSON(response.Make(nullable.GetNil(""), 0, responseErrors.GetErrorCode(fc, responseErrors.ErrInvalidBody)))
|
||||
}
|
||||
|
||||
var req struct {
|
||||
CustomerID uint `json:"customer_id"`
|
||||
IsNoVat bool `json:"is_no_vat"`
|
||||
}
|
||||
|
||||
if err := fc.Bind().Body(&req); err != nil {
|
||||
return fc.Status(responseErrors.GetErrorStatus(responseErrors.ErrJSONBody)).
|
||||
JSON(response.Make(nullable.GetNil(""), 0, responseErrors.GetErrorCode(fc, responseErrors.ErrJSONBody)))
|
||||
}
|
||||
|
||||
if err := h.service.SetCustomerNoVatStatus(req.CustomerID, req.IsNoVat); err != nil {
|
||||
return fc.Status(responseErrors.GetErrorStatus(err)).
|
||||
JSON(response.Make(nullable.GetNil(""), 0, responseErrors.GetErrorCode(fc, err)))
|
||||
}
|
||||
|
||||
return fc.JSON(response.Make(nullable.GetNil(""), 0, i18n.T_(fc, response.Message_OK)))
|
||||
}
|
||||
|
||||
@@ -35,6 +35,7 @@ type Customer struct {
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
UpdatedAt time.Time `json:"updated_at"`
|
||||
DeletedAt gorm.DeletedAt `gorm:"index" json:"-"`
|
||||
IsNoVat bool `gorm:"default:false" json:"is_no_vat"`
|
||||
}
|
||||
|
||||
func (u *Customer) HasPermission(permission perms.Permission) bool {
|
||||
|
||||
@@ -17,6 +17,7 @@ type UICustomerRepo interface {
|
||||
Find(langId uint, p find.Paging, filt *filters.FiltersList, search string) (*find.Found[model.UserInList], error)
|
||||
Save(customer *model.Customer) error
|
||||
Create(customer *model.Customer) error
|
||||
SetCustomerNoVatStatus(customerID uint, isNoVat bool) error
|
||||
}
|
||||
|
||||
type CustomerRepo struct{}
|
||||
@@ -114,3 +115,7 @@ func (repo *CustomerRepo) Save(customer *model.Customer) error {
|
||||
func (repo *CustomerRepo) Create(customer *model.Customer) error {
|
||||
return db.DB.Create(customer).Error
|
||||
}
|
||||
|
||||
func (repo *CustomerRepo) SetCustomerNoVatStatus(customerID uint, isNoVat bool) error {
|
||||
return db.DB.Model(&model.Customer{}).Where("id = ?", customerID).Update("is_no_vat", isNoVat).Error
|
||||
}
|
||||
|
||||
@@ -24,3 +24,7 @@ func (s *CustomerService) GetById(id uint) (*model.Customer, error) {
|
||||
func (s *CustomerService) Find(langId uint, p find.Paging, filt *filters.FiltersList, search string) (*find.Found[model.UserInList], error) {
|
||||
return s.repo.Find(langId, p, filt, search)
|
||||
}
|
||||
|
||||
func (s *CustomerService) SetCustomerNoVatStatus(customerID uint, isNoVat bool) error {
|
||||
return s.repo.SetCustomerNoVatStatus(customerID, isNoVat)
|
||||
}
|
||||
|
||||
22
bruno/api_v1/customer/Set is_no_vat.yml
Normal file
22
bruno/api_v1/customer/Set is_no_vat.yml
Normal file
@@ -0,0 +1,22 @@
|
||||
info:
|
||||
name: Set is_no_vat
|
||||
type: http
|
||||
seq: 4
|
||||
|
||||
http:
|
||||
method: PATCH
|
||||
url: "{{bas_url}}/restricted/customer/no-vat"
|
||||
body:
|
||||
type: json
|
||||
data: |-
|
||||
{
|
||||
"customer_id":1,
|
||||
"is_no_vat": false
|
||||
}
|
||||
auth: inherit
|
||||
|
||||
settings:
|
||||
encodeUrl: true
|
||||
timeout: 0
|
||||
followRedirects: true
|
||||
maxRedirects: 5
|
||||
@@ -112,7 +112,8 @@ CREATE TABLE IF NOT EXISTS b2b_customers (
|
||||
country_id INT NULL DEFAULT 2,
|
||||
created_at DATETIME(6) NULL,
|
||||
updated_at DATETIME(6) NULL,
|
||||
deleted_at DATETIME(6) NULL
|
||||
deleted_at DATETIME(6) NULL,
|
||||
is_no_vat TINYINT(1) NULL DEFAULT 0
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||||
|
||||
CREATE UNIQUE INDEX IF NOT EXISTS idx_customers_email
|
||||
|
||||
@@ -16,6 +16,7 @@ READS SQL DATA
|
||||
BEGIN
|
||||
|
||||
DECLARE v_tax_rate DECIMAL(10,4) DEFAULT 0;
|
||||
DECLARE v_tax_group INT;
|
||||
|
||||
DECLARE v_base_raw DECIMAL(20,6);
|
||||
DECLARE v_base DECIMAL(20,6);
|
||||
@@ -29,45 +30,54 @@ BEGIN
|
||||
|
||||
DECLARE v_has_specific INT DEFAULT 0;
|
||||
|
||||
-- currency
|
||||
DECLARE v_target_currency BIGINT;
|
||||
DECLARE v_target_rate DECIMAL(13,6) DEFAULT 1;
|
||||
DECLARE v_specific_rate DECIMAL(13,6) DEFAULT 1;
|
||||
|
||||
DECLARE v_is_no_vat TINYINT DEFAULT 0;
|
||||
|
||||
SET p_id_product_attribute = NULLIF(p_id_product_attribute, 0);
|
||||
|
||||
-- ================= CUSTOMER VAT =================
|
||||
SELECT COALESCE(c.is_no_vat, 0)
|
||||
INTO v_is_no_vat
|
||||
FROM b2b_customers c
|
||||
WHERE c.id = p_id_customer
|
||||
LIMIT 1;
|
||||
|
||||
-- ================= TAX GROUP =================
|
||||
SELECT ps.id_tax_rules_group
|
||||
INTO v_tax_group
|
||||
FROM ps_product_shop ps
|
||||
WHERE ps.id_product = p_id_product
|
||||
AND ps.id_shop = p_id_shop
|
||||
LIMIT 1;
|
||||
|
||||
-- ================= TAX =================
|
||||
SELECT COALESCE(t.rate, 0)
|
||||
INTO v_tax_rate
|
||||
FROM ps_tax_rule tr
|
||||
JOIN ps_tax t ON t.id_tax = tr.id_tax
|
||||
LEFT JOIN b2b_countries c ON c.id = p_id_country
|
||||
WHERE tr.id_tax_rules_group = (
|
||||
SELECT ps.id_tax_rules_group
|
||||
FROM ps_product_shop ps
|
||||
WHERE ps.id_product = p_id_product
|
||||
AND ps.id_shop = p_id_shop
|
||||
LIMIT 1
|
||||
)
|
||||
AND tr.id_country = c.ps_id_country
|
||||
WHERE tr.id_tax_rules_group = v_tax_group
|
||||
AND tr.id_country = c.ps_id_country
|
||||
LIMIT 1;
|
||||
|
||||
-- ================= TARGET CURRENCY =================
|
||||
SELECT c.b2b_id_currency
|
||||
INTO v_target_currency
|
||||
IF v_is_no_vat = 1 THEN
|
||||
SET v_tax_rate = 0;
|
||||
END IF;
|
||||
|
||||
-- ================= CURRENCY =================
|
||||
SELECT c.b2b_id_currency, r.conversion_rate
|
||||
INTO v_target_currency, v_target_rate
|
||||
FROM b2b_countries c
|
||||
LEFT JOIN b2b_currency_rates r
|
||||
ON r.b2b_id_currency = c.b2b_id_currency
|
||||
WHERE c.id = p_id_country
|
||||
LIMIT 1;
|
||||
|
||||
-- latest target rate
|
||||
SELECT r.conversion_rate
|
||||
INTO v_target_rate
|
||||
FROM b2b_currency_rates r
|
||||
WHERE r.b2b_id_currency = v_target_currency
|
||||
ORDER BY r.created_at DESC
|
||||
LIMIT 1;
|
||||
|
||||
-- ================= BASE PRICE (RAW) =================
|
||||
-- ================= BASE PRICE =================
|
||||
SELECT
|
||||
COALESCE(ps.price, p.price) + COALESCE(pas.price, 0)
|
||||
INTO v_base_raw
|
||||
@@ -79,8 +89,8 @@ BEGIN
|
||||
AND pas.id_shop = p_id_shop
|
||||
WHERE p.id_product = p_id_product;
|
||||
|
||||
-- convert base to target currency
|
||||
SET v_base = v_base_raw * v_target_rate;
|
||||
SET v_excl = v_base;
|
||||
|
||||
-- ================= RULE SELECTION =================
|
||||
SELECT
|
||||
@@ -99,71 +109,67 @@ BEGIN
|
||||
|
||||
FROM b2b_specific_price bsp
|
||||
|
||||
LEFT JOIN b2b_specific_price_product spp
|
||||
ON spp.b2b_specific_price_id = bsp.id
|
||||
AND spp.id_product = p_id_product
|
||||
|
||||
LEFT JOIN b2b_specific_price_product_attribute spa
|
||||
ON spa.b2b_specific_price_id = bsp.id
|
||||
AND spa.id_product_attribute = p_id_product_attribute
|
||||
|
||||
LEFT JOIN b2b_specific_price_customer spc
|
||||
ON spc.b2b_specific_price_id = bsp.id
|
||||
AND spc.b2b_id_customer = p_id_customer
|
||||
|
||||
LEFT JOIN b2b_specific_price_country spco
|
||||
ON spco.b2b_specific_price_id = bsp.id
|
||||
AND spco.b2b_id_country = p_id_country
|
||||
|
||||
LEFT JOIN b2b_specific_price_category spcat
|
||||
ON spcat.b2b_specific_price_id = bsp.id
|
||||
|
||||
LEFT JOIN ps_category_product cp
|
||||
ON cp.id_category = spcat.id_category
|
||||
AND cp.id_product = p_id_product
|
||||
|
||||
WHERE bsp.is_active = 1
|
||||
AND bsp.from_quantity <= p_quantity
|
||||
|
||||
-- intersection rules (unchanged)
|
||||
AND (
|
||||
NOT EXISTS (SELECT 1 FROM b2b_specific_price_product x WHERE x.b2b_specific_price_id = bsp.id)
|
||||
OR EXISTS (SELECT 1 FROM b2b_specific_price_product x WHERE x.b2b_specific_price_id = bsp.id AND x.id_product = p_id_product)
|
||||
)
|
||||
AND (spp.id_product IS NOT NULL OR NOT EXISTS (
|
||||
SELECT 1 FROM b2b_specific_price_product x WHERE x.b2b_specific_price_id = bsp.id
|
||||
))
|
||||
|
||||
AND (
|
||||
NOT EXISTS (SELECT 1 FROM b2b_specific_price_product_attribute x WHERE x.b2b_specific_price_id = bsp.id)
|
||||
OR EXISTS (SELECT 1 FROM b2b_specific_price_product_attribute x WHERE x.b2b_specific_price_id = bsp.id AND x.id_product_attribute = p_id_product_attribute)
|
||||
)
|
||||
AND (spa.id_product_attribute IS NOT NULL OR NOT EXISTS (
|
||||
SELECT 1 FROM b2b_specific_price_product_attribute x WHERE x.b2b_specific_price_id = bsp.id
|
||||
))
|
||||
|
||||
AND (
|
||||
NOT EXISTS (SELECT 1 FROM b2b_specific_price_category x WHERE x.b2b_specific_price_id = bsp.id)
|
||||
OR EXISTS (
|
||||
SELECT 1 FROM b2b_specific_price_category x
|
||||
JOIN ps_category_product cp ON cp.id_category = x.id_category
|
||||
WHERE x.b2b_specific_price_id = bsp.id AND cp.id_product = p_id_product
|
||||
)
|
||||
)
|
||||
AND (spc.b2b_id_customer IS NOT NULL OR NOT EXISTS (
|
||||
SELECT 1 FROM b2b_specific_price_customer x WHERE x.b2b_specific_price_id = bsp.id
|
||||
))
|
||||
|
||||
AND (
|
||||
NOT EXISTS (SELECT 1 FROM b2b_specific_price_customer x WHERE x.b2b_specific_price_id = bsp.id)
|
||||
OR EXISTS (SELECT 1 FROM b2b_specific_price_customer x WHERE x.b2b_specific_price_id = bsp.id AND x.b2b_id_customer = p_id_customer)
|
||||
)
|
||||
AND (spco.b2b_id_country IS NOT NULL OR NOT EXISTS (
|
||||
SELECT 1 FROM b2b_specific_price_country x WHERE x.b2b_specific_price_id = bsp.id
|
||||
))
|
||||
|
||||
AND (
|
||||
NOT EXISTS (SELECT 1 FROM b2b_specific_price_country x WHERE x.b2b_specific_price_id = bsp.id)
|
||||
OR EXISTS (SELECT 1 FROM b2b_specific_price_country x WHERE x.b2b_specific_price_id = bsp.id AND x.b2b_id_country = p_id_country)
|
||||
)
|
||||
AND (cp.id_product IS NOT NULL OR NOT EXISTS (
|
||||
SELECT 1 FROM b2b_specific_price_category x WHERE x.b2b_specific_price_id = bsp.id
|
||||
))
|
||||
|
||||
ORDER BY
|
||||
-- customer wins
|
||||
(EXISTS (SELECT 1 FROM b2b_specific_price_customer x WHERE x.b2b_specific_price_id = bsp.id AND x.b2b_id_customer = p_id_customer)) DESC,
|
||||
|
||||
-- attribute
|
||||
(EXISTS (SELECT 1 FROM b2b_specific_price_product_attribute x WHERE x.b2b_specific_price_id = bsp.id AND x.id_product_attribute = p_id_product_attribute)) DESC,
|
||||
|
||||
-- product
|
||||
(EXISTS (SELECT 1 FROM b2b_specific_price_product x WHERE x.b2b_specific_price_id = bsp.id AND x.id_product = p_id_product)) DESC,
|
||||
|
||||
-- category
|
||||
(EXISTS (
|
||||
SELECT 1 FROM b2b_specific_price_category x
|
||||
JOIN ps_category_product cp ON cp.id_category = x.id_category
|
||||
WHERE x.b2b_specific_price_id = bsp.id AND cp.id_product = p_id_product
|
||||
)) DESC,
|
||||
|
||||
-- country
|
||||
(EXISTS (SELECT 1 FROM b2b_specific_price_country x WHERE x.b2b_specific_price_id = bsp.id AND x.b2b_id_country = p_id_country)) DESC,
|
||||
|
||||
(spc.b2b_id_customer IS NOT NULL) DESC,
|
||||
(spa.id_product_attribute IS NOT NULL) DESC,
|
||||
(spp.id_product IS NOT NULL) DESC,
|
||||
(cp.id_product IS NOT NULL) DESC,
|
||||
(spco.b2b_id_country IS NOT NULL) DESC,
|
||||
bsp.id DESC
|
||||
|
||||
LIMIT 1;
|
||||
|
||||
-- ================= APPLY =================
|
||||
SET v_excl = v_base;
|
||||
|
||||
IF v_has_specific = 1 THEN
|
||||
|
||||
IF v_reduction_type = 'amount' THEN
|
||||
|
||||
-- convert specific price currency if needed
|
||||
IF v_specific_currency_id IS NOT NULL AND v_specific_currency_id != v_target_currency THEN
|
||||
|
||||
SELECT r.conversion_rate
|
||||
@@ -173,7 +179,6 @@ BEGIN
|
||||
ORDER BY r.created_at DESC
|
||||
LIMIT 1;
|
||||
|
||||
-- normalize → then convert to target
|
||||
SET v_excl = (v_fixed_price / v_specific_rate) * v_target_rate;
|
||||
|
||||
ELSE
|
||||
|
||||
Reference in New Issue
Block a user