https://pastein.ru/t/su

  скопируйте уникальную ссылку для отправки


CREATE DEFINER=`root`@`localhost` FUNCTION `lkdata2`.`RecordOrders`(IdCounterparty CHAR(11), UserID CHAR(11), OrderStatus INT(2), Discount INT(3),  IdProductQuantity VARCHAR(1000)) RETURNS char(50) CHARSET utf8
BEGIN #обновлено +
	

	/* Данная функция записывает заказ. На входе id контрагента, id пользователя, статус заказа, размер скидки от 1 до 100 %, и json массив вида:
  '[{"Idproduct": "00000036402", "Quantity": "4"},
	{"Idproduct": "00000036405", "Quantity": "5"},
	{"Idproduct": "00000036522", "Quantity": "10"}]'    , на выходе 1 - если записалось, 0 если json строка не валидна.*/
    
    #вся строка для проверки
    /*
    select lkdata2.RecordOrders('000005359', '1', 1,2, '[{"Idproduct": "00000036402", "Quantity": "4"},
														  {"Idproduct": "00000036405", "Quantity": "5"},
														  {"Idproduct": "00000036522", "Quantity": "10"}]');
    */
	
	DECLARE sysdate datetime; # системное время
    DECLARE currentYear int(4); # текущий год
	DECLARE startDate datetime; # дату начала года
	DECLARE newID float(11,2); # новый id
	DECLARE newInvoiceNum int(10) ZEROFILL; # zerofill - заполнение нулями пустых значений переменной newID
	DECLARE newInvoiceNumAndPrefix char(11); # newInvoiceNum c префиксом W
	DECLARE contract_number char(11); # номер договора
	DECLARE res tinyint(1); # тип договора
	DECLARE nds int(2); # налог %
	DECLARE ndsSumm float(15,2); # сумма НДС р
	DECLARE nameProduct varchar(100); # имя продукта
	DECLARE typeCost char(1); # тип цены. розница=0 мелкий опт=1 крупный опт=2
    DECLARE costProduct float(15,2); # цена продукта учитывая тип
    DECLARE ProdID char(11); #id продукта в цикле
    DECLARE QuantityProduct float(10,3); # колличество конкретного продукта
	DECLARE total_cost_of_products float(15,2); # цена продукта учитывая колличество и НДС.
    DECLARE DimensionProduct char(3); # еденица измерения
	DECLARE l INT UNSIGNED; # Длина json
	DECLARE i INT UNSIGNED; # только положительные значения
    DECLARE RELEASELOCK tinyint(1); # Освобождение именованого замка 1 если освободился 0 если нет
    DECLARE cost float(15,2); # Общая сумма

	IF (GET_LOCK('lock', 1) = 0) THEN RETURN 0; #Замок
	END IF;
			SET sysdate = sysdate(); # присвоение серверного времени
			SET currentYear = YEAR(sysdate()); # присвоение текущего года
			SET startDate = CAST(DATE_FORMAT(sysdate(), '%Y-01-01') AS datetime);
			# Сборка даты и времени(т.к. время не указано, то оно 00:00:00) начала года (тип данных date) без преведения типов
			SET newID = LEAST((currentYear-2000)/100, (SELECT min(Invoice.id) FROM Invoice 
			WHERE (((Invoice.id)*100)%100) + (currentYear-2000) = 0 AND Invoice.id <= 0)) - 1;
			# Генерация нового id, если больше 0, тогда 0, иначе 0-1=-1.
			INSERT INTO Invoice (id) VALUES (newID); # добавление уникального id 
-- 			SET newID = LAST_INSERT_ID();
    SET RELEASELOCK = (SELECT RELEASE_LOCK('lock')); # Снятие замка
    /*
    if newID = 0 THEN Return concat('id не найден', newID);
    END if;*/
    
    SET cost = 0; # обнуление общей стоимости
	SET newInvoiceNum = ABS(newID); # убирает знак
	SET newInvoiceNumAndPrefix = concat('W', newInvoiceNum); # собирает строку вида W0000000000
	SET contract_number = (SELECT MainContractId FROM Companies WHERE Companies.CompanyId = IdCounterparty); # номер договора
    SET typeCost = (SELECT Contracts.CostType FROM Contracts WHERE Contracts.ContractId = contract_number); # тип договора
    SET Discount = COALESCE(Discount, 0); # если скидка не указана, значит она равна 0
    
    SET res = (SELECT Companies.Resident FROM Companies WHERE Companies.CompanyId = IdCounterparty); # тип договора
	IF res = 0 # выбор НДС в зависимости от типа договора
		THEN SET nds = 20;
		ELSE SET nds = 0;
	END IF; # Данный блок находится тут, потому что используется и в цикле и после него
        
	SET l = JSON_LENGTH(IdProductQuantity); # узнаем длиину массива начиная с единицы
	SET i = 0; # объявляем переменную-счетчик
		 
	IF (NOT JSON_VALID(IdProductQuantity)) THEN RETURN 0;
	END IF;
    
	WHILE i < l DO  # цикл счетчик всех элеменнтов массива json
		SET ProdID = TRIM(BOTH '"' FROM JSON_EXTRACT(IdProductQuantity, CONCAT('$[', i, '].Idproduct'))); # вытаскиваю id продукта из json
        SET QuantityProduct = TRIM(BOTH '"' FROM JSON_EXTRACT(IdProductQuantity, CONCAT('$[', i, '].Quantity'))); # вытаскиваем колличество конкретной продукции из json
        
		CASE # определение стоимости продукта
			WHEN typeCost = 0 THEN SET costProduct = (SELECT price0 FROM Price WHERE Price.ProductId = ProdID) / 100 * (100 - Discount); # розница с учетом скидки
			WHEN typeCost = 1 THEN SET costProduct = (SELECT price1 FROM Price WHERE Price.ProductId = ProdID); # мелки опт
			WHEN typeCost = 2 THEN SET costProduct = (SELECT price2 FROM Price WHERE Price.ProductId = ProdID); # крупный опт
		END CASE; 
        
        SET total_cost_of_products = (QuantityProduct * costProduct) + ((QuantityProduct * costProduct) * nds / 100); # сумма количества всех продуктов
        
		SET DimensionProduct = (SELECT Dimension FROM Price WHERE Price.ProductId = ProdID); # запись еденицы измерения
        
		INSERT INTO InvoiceItem 
		(InvoiceId, ProductId, Quantity, QuantityNeed, Cost, CostPart, Dimension) 	# опредиление полей вставки таблицы
		VALUES  
		(newID, ProdID, QuantityProduct, QuantityProduct, costProduct, total_cost_of_products, DimensionProduct); # вставляемые значения

		SET cost = cost + total_cost_of_products;
        
		SET i := i + 1; # приращение счетчика
	END WHILE;

	# запись НДС %
	SET ndsSumm = (cost * nds / 100); # запись суммы НДС
        UPDATE Invoice
		SET 
        Invoice.CostSumm = cost,
        Invoice.TaxSumm = ndsSumm,
        Invoice.TaxRate = nds,
        Invoice.InvoiceNum = newInvoiceNumAndPrefix,
        Invoice.InvoiceDate = sysdate,
        Invoice.CompanyId = IdCounterparty,
        Invoice.ContractId = contract_number,
        Invoice.UserId = UserID,
        Invoice.Status = OrderStatus
		WHERE Invoice.id = newID;  
    
	RETURN 1;

END