Snippets Collections
curl --location 'localhost:9091/chatbot/report/update-data-job' \
--header 'Content-Type: application/json' \
--data '{
    "start_date":"25/01/2024",
    "end_date":"20/08/2024"
}'

curl --location 'localhost:9091/chatbot/report/update-analytic-user' \
--header 'Content-Type: application/json' \
--data '{
    "start_date":"25/01/2024",
    "end_date":"20/08/2024"
}'

import random
names = [
    "黄彦祯",
    "陈子睿",
    "杨芷涵",
    "李若璇",
    "麦家俊",
    "蔡培钧",
    "李泽丰",
    # "陈蓬宇",
    "郭芃泽"
    ]
    
random.shuffle(names)

for idx, name in enumerate(names):
    end_symb = " " if idx%2==0 else " | "
    print(f"{name}", end=end_symb)
    
{
	"blocks": [
		{
			"type": "header",
			"text": {
				"type": "plain_text",
				"text": ":star: What's on in Melbourne this week! :star:"
			}
		},
		{
			"type": "section",
			"text": {
				"type": "mrkdwn",
				"text": "\n\n Hey Melbourne, happy Monday! Please see below for what's on this week. "
			}
		},
		{
			"type": "divider"
		},
		{
			"type": "header",
			"text": {
				"type": "plain_text",
				"text": "Xero Café :coffee:",
				"emoji": true
			}
		},
		{
			"type": "section",
			"text": {
				"type": "mrkdwn",
				"text": "\n :new-thing: *This week we are offering:* \n\n We have Raspberry Yo-Yo Biscuits (GF), Chocolate Dotty Biscuits, and Vegan Chocolate & Raspberry Slice!\n\n *Weekly Café Special*: _Matcha Latte_"
			}
		},
		{
			"type": "header",
			"text": {
				"type": "plain_text",
				"text": " Wednesday, 28th August :calendar-date-28:",
				"emoji": true
			}
		},
		{
			"type": "section",
			"text": {
				"type": "mrkdwn",
				"text": "\n\n:late-cake: *Afternoon Tea*: From *2pm* in the *L1, L2 and L3* kitchens! \n\n:massage:*Wellbeing - Pilates Class*: Confirm your spot <https://docs.google.com/spreadsheets/d/1ZpZnKeVds8e4Ue8g0tpe9Nv2jKXSqBUkfgzYfQu1hOA/edit?gid=0#gid=0/|*here*>. Please note we have a maximum of 15 participants per class, a minimum notice period of 2 hours is required if you can no longer attend."
			}
		},
		{
			"type": "header",
			"text": {
				"type": "plain_text",
				"text": " Thursday, 29th August :calendar-date-29:",
				"emoji": true
			}
		},
		{
			"type": "section",
			"text": {
				"type": "mrkdwn",
				"text": ":breakfast: *Breakfast*: Provided by *Kartel Catering* from *8:30am - 10:30am* in the Wominjeka Breakout Space.\n\n"
			}
		},
		{
			"type": "divider"
		},
		{
			"type": "section",
			"text": {
				"type": "mrkdwn",
				"text": "Stay tuned to this channel for more details, and make sure you're subscribed to the <https://calendar.google.com/calendar/u/0?cid=Y19xczkyMjk5ZGlsODJzMjA4aGt1b3RnM2t1MEBncm91cC5jYWxlbmRhci5nb29nbGUuY29t|*Melbourne Social Calendar*> :party-wx:"
			}
		}
	]
}
let vLoopTablecommaCount=SubStringCount(vTables,',');

trace $(section) finnal vTables $(vTables);

for i=2 to vLoopTablecommaCount + 1    

  let t = subfield(vTables,',', i);

  trace $(1) loop store met t $(t);


  HTM_RESET:
  NoConcatenate
  LOAD Null() AS DummyField
  AUTOGENERATE 0;


  STORE HTM_RESET INTO [$(vEnvironmentPathQvd)/$(t).qvd] (qvd);

  LET vRows = NoOfRows('$(t)');
  TRACE $(t) has $(vRows) rows;

	STORE $(t) INTO [$(vEnvironmentPathQvd)/$(t).qvd] (qvd);
    
      
  drop table  $(t);

next

{
	"blocks": [
		{
			"type": "header",
			"text": {
				"type": "plain_text",
				"text": ":sparkles: Boost Days - Whats On This Week! :sparkles:"
			}
		},
		{
			"type": "section",
			"text": {
				"type": "mrkdwn",
				"text": "Mōrena Ahuriri & happy Monday! :smiling-hand-over-mouth:\n\nWe're excited to bring you another great week in the office with our Boost Day Program! :yay: Please see below for whats on this week :arrow-bounce:"
			}
		},
		{
			"type": "divider"
		},
		{
			"type": "header",
			"text": {
				"type": "plain_text",
				"text": ":calendar-date-20: Wednesday, 20th November",
				"emoji": true
			}
		},
		{
			"type": "section",
			"text": {
				"type": "mrkdwn",
				"text": "\n:coffee: *Café Partnership*: Enjoy coffee and café-style beverages from our cafe partner, *Adoro*, located in our office building *8:00AM - 11:30AM*.\n:cake: *Afternoon Tea*: Provided by *Mitzi and Twinn* *2:00PM - 3:00PM* in the Kitchen."
			}
		},
		{
			"type": "header",
			"text": {
				"type": "plain_text",
				"text": ":calendar-date-21: Thursday, 21st November",
				"emoji": true
			}
		},
		{
			"type": "section",
			"text": {
				"type": "mrkdwn",
				"text": ":coffee: *Café Partnership*: Enjoy coffee and café-style beverages from our cafe partner, *Adoro*, located in our office building *8:00AM - 11:30AM*. \n:breakfast: *Breakfast*: Provided by *Roam* *9:30AM - 11:00AM* in the Kitchen."
			}
		},
		{
			"type": "divider"
		},
		{
			"type": "section",
			"text": {
				"type": "mrkdwn",
				"text": "*LATER THIS MONTH:*"
			}
		},
		{
			"type": "section",
			"text": {
				"type": "mrkdwn",
				"text": "*Friday, 22nd November* \n:unicorn_face: *RSVP Deadline for EOY Event*: Register <https://xero-wx.jomablue.com/reg/store/eoy_hwk|*here*> :magic_wand:\n\n*Wednesday, 27th November*\n:xero: *Global All Hands*: Streaming in Clearview *11:00AM - 12:00PM*."
			}
		},
		{
			"type": "section",
			"text": {
				"type": "mrkdwn",
				"text": "Stay tuned to this channel for more details, check out the <https://calendar.google.com/calendar/u/0?cid=eGVyby5jb21fbXRhc2ZucThjaTl1b3BpY284dXN0OWlhdDRAZ3JvdXAuY2FsZW5kYXIuZ29vZ2xlLmNvbQ|*Hawkes Bay Social Calendar*>, and get ready to Boost your workdays!\n\nWX Team :party-wx:"
			}
		}
	]
}
ARC-Seal: i=5; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=pass;
 b=BsuHmlhzDNhTg4Am+jEuS6W2FRKgICcM2auxhs9ZteQC1KXxsj0X1dxaFvosVn/W66niRSiUpC7NdkFbb1nwDaslbNImw5lbkA2tp3NNaiYIv6J4ca5QkrGxS6zdV02H8aYzaKoBPT62om+euvXC/R7eEMW+b3Kq1Q4FN+gUw3VNEt9vDSDXoenjFcRKSfIQpXnUhLGEuE+K3pA+N3GUdvgSABkLvRTH+km+Y8c8+zKU06oBAoD+6QjYxWJo/wduwGsxQ7pjaRpYITTKfHyqWjY4RYbPx/mrm8pijQVoB5ZLsYqqaJuIsaHr/jOFtGSC6h37KDz7DotG0HFTo6tIIg==
ARC-Message-Signature: i=5; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com;
 s=arcselector9901;
 h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1;
 bh=BTH7KZd88CdQkmmYtaAP6jrzQMdK5mxhJB3u5xBaI7c=;
 b=fPSDwu8f7BIRHNe7noEh1LociGFVfpzzLZfQJTPq8POZItBFAcdG8VV3hmIA4M+KLuB3AEO64VoBmUtPYrdc5xospH00CuDOK8s2qfpXY+8KRnjDwm1uitMfONao2ax+I7klNDg1icrhdROzbuU8B/Or1TKTKrlAU4c7HAOcZobpatxinjVWYXnlQjdZIeShJGO0ItrhClgCv9IKBF6Mt1mezFQtaRdKiinXMNdYuV+L159VdxF1DGQAuMv9CyCrZ+wzy7ckcOUYbLqqdnJXiw1EqkktBamJKzEWcfbdnT0wXNa1efgwMxc1wZ1t31+Lao+FIQuRGlmMEwrRbJMo/g==
ARC-Authentication-Results: i=5; mx.microsoft.com 1; spf=softfail (sender ip
 is 104.47.56.41) smtp.rcpttodomain=accountprotection.microsoft.com
 smtp.mailfrom=gmail.com; dmarc=pass (p=none sp=quarantine pct=100)
 action=none header.from=gmail.com; dkim=pass (signature was verified)
 header.d=gmail.com; arc=pass (0 oda=1 ltdi=1
 spf=[1,1,smtp.mailfrom=gmail.com] dkim=[1,3,header.d=gmail.com]
 dmarc=[1,3,header.from=gmail.com])
ARC-Seal: i=4; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=pass;
 b=IMptFPWi1RPQyXU9oPt6tZbE0P2KvTOY7hH/XN6fvtgKA7cEQmEiQNcVFFlCs1QbX+lBuen6ARWIjvsPU8hrYC36Uuq1Bsve5C8yT/jKeAnwoDScj5xKRdlBinCPeNinTrvaFyXcwq7YWw9qFcbxpxzMcTY3irziEF8PikXUBppFXNaP2TNLKNWtZB1JCewxcEq4pebioKorDNdtJcLdGefOKE7gL57Ox4k46yBO6nCfEjU8kQKcRNWujitPS2OYr0yCO7c/dTrEIEShs+offi48cZT4z9KImF6z+zrMaCeAHJXippYo1vJ54QVqVXtKTcA0U2uHpbe4FQM+xGHKCg==
ARC-Message-Signature: i=4; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com;
 s=arcselector9901;
 h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1;
 bh=BTH7KZd88CdQkmmYtaAP6jrzQMdK5mxhJB3u5xBaI7c=;
 b=ZJR+xCNmC1z0qEyWlumGSg2Yx5aRGZbo+aIRGBsRUDUfwHRvUUzG0ftmvYUw3YdNFoMenweBLb7hsuBrIEkAIVOGuM7Al9L+0AHCA661rpJ8nH5WEBA6i26T7OgLGpTYStAeI9FhjdnsU6mSHWu1rfFdACUeM1iOLDvhF4QA5jJt0T3+5vAwEh6JhRnk3A6/FLzO4ylG0rEQrHYlvd3DElVDf7fJzpvIj4nzfYUSiz12TkOWOA7G3huWmzkHLISPP7i6SB8VJIL1N+MF8vLvPONMLOkaqG9E59qw0S/vQSCRekwEX7eEnn+WBc8THqVfHkuVp6h4bxynaAj4iKucSA==
ARC-Authentication-Results: i=4; mx.microsoft.com 1; spf=softfail (sender ip
 is 104.47.56.41) smtp.rcpttodomain=accountprotection.microsoft.com
 smtp.mailfrom=gmail.com; dmarc=pass (p=none sp=quarantine pct=100)
 action=none header.from=gmail.com; dkim=pass (signature was verified)
 header.d=gmail.com; arc=pass (0 oda=1 ltdi=1
 spf=[1,1,smtp.mailfrom=gmail.com] dkim=[1,3,header.d=gmail.com]
 dmarc=[1,3,header.from=gmail.com])
Received: from BLAPR05CA0011.namprd05.prod.outlook.com (2603:10b6:208:36e::26)
 by PH0PR16MB4947.namprd16.prod.outlook.com (2603:10b6:510:122::6) with
 Microsoft SMTP Server (version=TLS1_2,
 cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.7611.22; Tue, 28 May
 2024 11:26:08 +0000
Received: from BL02EPF0001A107.namprd05.prod.outlook.com
 (2603:10b6:208:36e:cafe::b4) by BLAPR05CA0011.outlook.office365.com
 (2603:10b6:208:36e::26) with Microsoft SMTP Server (version=TLS1_2,
 cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.7633.18 via Frontend
 Transport; Tue, 28 May 2024 11:26:08 +0000
Authentication-Results: spf=softfail (sender IP is 104.47.56.41)
 smtp.mailfrom=gmail.com; dkim=pass (signature was verified)
 header.d=gmail.com;dmarc=pass action=none header.from=gmail.com;compauth=pass
 reason=100
Received-SPF: SoftFail (protection.outlook.com: domain of transitioning
 gmail.com discourages use of 104.47.56.41 as permitted sender)
Received: from NAM02-DM3-obe.outbound.protection.outlook.com (104.47.56.41) by
 BL02EPF0001A107.mail.protection.outlook.com (10.167.241.136) with Microsoft
 SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id
 15.20.7633.15 via Frontend Transport; Tue, 28 May 2024 11:26:07 +0000
ARC-Seal: i=3; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=pass;
 b=QQsjhoFwmWgga7QgVmuiIpjolT3qoIfC4UyvaIHtrBUoZbL8vGnLJaHz1yFT5RgYKdXEcGujhWfYQsO/Ywz89jFMhRJOiUBlGdjNSAvKjqI48DSr+4vbSfup6MSk82yVq9gjo9CQpF3gKvEdHAsZCR6qLQVVODaFC38ZGLqkzbL9dndK6W3DOGQ2Fe7EkzKQZAXq55dnSn2k/CFL20D8qIAuNLhhl8TZmHJdIqSl1e9FBGNrvMSGAD9P9as77FpELjYOK8RBCabTQfXLH3cDfCZOWUGwmwsj9oRyInxiYrT/41AE1RBxJmHVKIsuXwqNUSpqE0v49mz9knUYvWeQhA==
ARC-Message-Signature: i=3; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com;
 s=arcselector9901;
 h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1;
 bh=BTH7KZd88CdQkmmYtaAP6jrzQMdK5mxhJB3u5xBaI7c=;
 b=UkduSxg3NiLVpagTOGhOahgYqbN8xvnOdx8QjBBjqDAvtlgP9fpNcl7XWVrPMTyS7dyLid2PPIUnXjtFvX/ickz77F6MuwHx9NokSQY/JMZwxUkN9+7QoKHA5JE4abavik9NnxK23ojlTOOkAAoPk95COX03M7r/fnYw/yEGe1tL07mHuutGZrUe0cUhTdDPmuSkwApA1Q7nuU3ndxaZ+eE0fGoy5vHuUZdSz/XOl1iVc/LF8JYSOg4K/JkfS6h+4wv0DLtMKqfVMUiLsVXwX1ojIrkB9G7n/8lL4nSTsQ/cPuBrT+jsoiO+0ohGJVCaQWw1MtGh8n/cGoiZPtpr/A==
ARC-Authentication-Results: i=3; mx.microsoft.com 1; spf=softfail (sender ip
 is 104.47.58.101) smtp.rcpttodomain=accountprotection.microsoft.com
 smtp.mailfrom=gmail.com; dmarc=pass (p=none sp=quarantine pct=100)
 action=none header.from=gmail.com; dkim=pass (signature was verified)
 header.d=gmail.com; arc=pass (0 oda=1 ltdi=1
 spf=[1,1,smtp.mailfrom=gmail.com] dkim=[1,1,header.d=gmail.com]
 dmarc=[1,1,header.from=gmail.com])
ARC-Seal: i=2; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=pass;
 b=LglrIZQAiASG6ZPXPXwZnYKd28LkKldRyXEdVlBXsvsdB6BX4aEDHYzVHo3rq2l6REoE03afSlLRURoleHcepg5mjzUYsDZsGYEzvuvp3VgJGpIDUB/g16kp69n8zVzpaOFCj8OJeWNaVDLG9ROQY5Y+dLS4lqAQuZwUuh1tBBfRcPy9gHot7Py4MqRu/Aqxt1nY7Cvf94kqWm2km6b5NdBElXEzUMstv7R+lTo1sFZ5S9z56Ror4dz4FbHUMu5N+hO+/bTt/UHfgeJd9sKV6qK22VhISNK3GhZOg+YCEVJyP22+It2agJIZHUgAnqw/s2dsWRXbfzDJWjUvcgMx9g==
ARC-Message-Signature: i=2; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com;
 s=arcselector9901;
 h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1;
 bh=BTH7KZd88CdQkmmYtaAP6jrzQMdK5mxhJB3u5xBaI7c=;
 b=XCXqb+akjBYXsQV17MxQFv3rC1661w9gINNtvRsSAlmjbNARiyBKdMn0mZOhCZYbNuLMIPGsYNbJYy2AX+X7mmDcVysXJaVGFmTXJYXpY5syMF4DdCznFP74B/r7bxN/uks7FUPD/RIoGKAYUeHbjkD0ulImKiwSDHNDHVBUTXxAUDZZ4j3PIYremVBW2i1V2u1FOnveU+TXh9Z23EM5rJ12QgjeseDvfX6jKY4BUinl0Lk+dYjLJS+UgqYz+ZYjVlK/VK5ErXCeEY9MrGEIfhHRMsEfTAi85AoyQu8fM+otQtZO8N8uWyYKsJB+B2GZGfvZnTaYOGgo5aLjAXKvEA==
ARC-Authentication-Results: i=2; mx.microsoft.com 1; spf=softfail (sender ip
 is 104.47.58.101) smtp.rcpttodomain=accountprotection.microsoft.com
 smtp.mailfrom=gmail.com; dmarc=pass (p=none sp=quarantine pct=100)
 action=none header.from=gmail.com; dkim=pass (signature was verified)
 header.d=gmail.com; arc=pass (0 oda=1 ltdi=1
 spf=[1,1,smtp.mailfrom=gmail.com] dkim=[1,1,header.d=gmail.com]
 dmarc=[1,1,header.from=gmail.com])
Received: from CH2PR11CA0021.namprd11.prod.outlook.com (2603:10b6:610:54::31)
 by SA0PR16MB3776.namprd16.prod.outlook.com (2603:10b6:806:87::22) with
 Microsoft SMTP Server (version=TLS1_2,
 cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.7611.31; Tue, 28 May
 2024 11:26:06 +0000
Received: from CH1PEPF0000AD74.namprd04.prod.outlook.com
 (2603:10b6:610:54:cafe::54) by CH2PR11CA0021.outlook.office365.com
 (2603:10b6:610:54::31) with Microsoft SMTP Server (version=TLS1_2,
 cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.7611.30 via Frontend
 Transport; Tue, 28 May 2024 11:26:06 +0000
Authentication-Results-Original: spf=softfail (sender IP is 104.47.58.101)
 smtp.mailfrom=gmail.com; dkim=pass (signature was verified)
 header.d=gmail.com;dmarc=pass action=none header.from=gmail.com;compauth=pass
 reason=100
Received-SPF: SoftFail (protection.outlook.com: domain of transitioning
 gmail.com discourages use of 104.47.58.101 as permitted sender)
Received: from NAM10-DM6-obe.outbound.protection.outlook.com (104.47.58.101)
 by CH1PEPF0000AD74.mail.protection.outlook.com (10.167.244.52) with Microsoft
 SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id
 15.20.7633.15 via Frontend Transport; Tue, 28 May 2024 11:26:06 +0000
ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none;
 b=ixRw5UhaCeagU2rZxXe09CKUgFELb2JwdpmA06hLVHCqDCeAupzNihrcbye47d+tM83eqVFSVfkNP74dKMtRgNRzCoXHbG1pb9kedKcB8dqq1Xav9MwWnonnedgHjaNtWrohVTC1kCjOBu7Q5MRbBPougbeRXIyuxB+1Ghr0WjHBSH8N/8LCtdf8idexpLYkLYFlXI5W/sTK6E2LRiB+poEbJoxwdBxy+mktTDItTnac4Bv7eARKJjPYsNETyum21ZuMYyiEclVSKckGQyP3gEXOlLRoh8+lr8m8zhk87HDUjBlu2/AFKSKp12UAj/qpwRTRIZHjsTyqVngYLRPMKQ==
ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com;
 s=arcselector9901;
 h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1;
 bh=BTH7KZd88CdQkmmYtaAP6jrzQMdK5mxhJB3u5xBaI7c=;
 b=b3Xjzwgal8pvOeMdHMxjg8iQJnilXl/z2Nnk0BEBngkV0w8dZNbSL9wrn7d1SIThrzxaIepe+j/jhHmMFswYIeaGTI/qG5/pJ5TBbGzmuMizqT/ieNyFRL9hIzlfbeiOreRo2Ur3oXwaIZ8BfcDniXrtArspuLPa48S9SVorydw93gDRh60eN9PUOXfempnzKM5NllxeFw7za2T2oyi5SzZHQPKHtPu8J6GQUmhypBdmWp5/nVzQCUSOVvaibbRvoYo+7hTtvcbNduHBwXxtuuzK6B7T2brvIpST4fFXEcDn3SjhEQLh5WwhHJlgsvtuTqz+wvyf9YhKvlPCle9eiQ==
ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass (sender ip is
 209.85.219.174) smtp.rcpttodomain=accountprotection.microsoft.com
 smtp.mailfrom=gmail.com; dmarc=pass (p=none sp=quarantine pct=100)
 action=none header.from=gmail.com; dkim=pass (signature was verified)
 header.d=gmail.com; arc=none (0)
Received: from SJ0PR13CA0064.namprd13.prod.outlook.com (2603:10b6:a03:2c4::9)
 by MN6PR16MB5430.namprd16.prod.outlook.com (2603:10b6:208:475::8) with
 Microsoft SMTP Server (version=TLS1_2,
 cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.7611.29; Tue, 28 May
 2024 11:26:05 +0000
Received: from CO1PEPF000042AA.namprd03.prod.outlook.com
 (2603:10b6:a03:2c4:cafe::a8) by SJ0PR13CA0064.outlook.office365.com
 (2603:10b6:a03:2c4::9) with Microsoft SMTP Server (version=TLS1_2,
 cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.7633.18 via Frontend
 Transport; Tue, 28 May 2024 11:26:04 +0000
Authentication-Results-Original: spf=pass (sender IP is 209.85.219.174)
 smtp.mailfrom=gmail.com; dkim=pass (signature was verified)
 header.d=gmail.com;dmarc=pass action=none header.from=gmail.com;compauth=pass
 reason=100
Received-SPF: Pass (protection.outlook.com: domain of gmail.com designates
 209.85.219.174 as permitted sender) receiver=protection.outlook.com;
 client-ip=209.85.219.174; helo=mail-yb1-f174.google.com; pr=C
Received: from mail-yb1-f174.google.com (209.85.219.174) by
 CO1PEPF000042AA.mail.protection.outlook.com (10.167.243.39) with Microsoft
 SMTP Server (version=TLS1_3, cipher=TLS_AES_256_GCM_SHA384) id 15.20.7633.15
 via Frontend Transport; Tue, 28 May 2024 11:26:03 +0000
Received: by mail-yb1-f174.google.com with SMTP id 3f1490d57ef6-df4e40a3cb6so722045276.0
        for <postmaster@accountprotection.microsoft.com>; Tue, 28 May 2024 04:26:03 -0700 (PDT)
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
        d=gmail.com; s=20230601; t=1716895563; x=1717500363; darn=accountprotection.microsoft.com;
        h=to:subject:message-id:date:from:mime-version:from:to:cc:subject
         :date:message-id:reply-to;
        bh=BTH7KZd88CdQkmmYtaAP6jrzQMdK5mxhJB3u5xBaI7c=;
        b=KZPhICQbL1uYh/OXVakyeJ2pKZ5WWekwudrDaIvXvv80PWYWAQcVzyHvxld5oBC6Dh
         GnakbKuXuHX2FKfirPIzeAfjzYbf1x+gnl+pht5i+1Qxx8WmI2Q8281oTVTsnx/LKslo
         W+C8/q2uGueZm/EFnU6Bf+EEUWBI3IJ5nIbx97P5dmLnWCZX1k0Q3B+ax3BHtJFCYESc
         mzEJnXjtW+HgJ0y65nhEPok8L/WslcpXzXjsxF/B06BSi5QGJOYmpYCH8CPyFTVXbOu/
         P/dDrrH0E75ntugVaf0w1PulH+pFs1GBEHSBDUDoA98+mRxMx5cZ8KGmiswmXCw0YDpu
         R9qw==
X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
        d=1e100.net; s=20230601; t=1716895563; x=1717500363;
        h=to:subject:message-id:date:from:mime-version:x-gm-message-state
         :from:to:cc:subject:date:message-id:reply-to;
        bh=BTH7KZd88CdQkmmYtaAP6jrzQMdK5mxhJB3u5xBaI7c=;
        b=CvJ/X/sTQb2b6eHlagEUa2fRD+lE3cSNAnr6SqKKJamyBWAsBNA4Frg+g/Og50zoDZ
         8sd8+Rb/CuihTey8zHeRbKYH1e4SDx7tvIMx3hYjfuzMmqCc0cIyblwoIT1SMSQbhoEj
         mX/uY/iokaLVcJba5M8qubAulP+0TupXUarVoIU+2hvH7kLTJY3GdWC0FS16uxpGoaEr
         QApEkYbgOzpq8JnL1+piKoYJLUkXyQUAProVXg8bNThbiv8pgs5kyjuIOmJq1PgroiE2
         VCJpHQMpwnYBtJR9vryhK6f74NyUP6s2C5G007XqaqPdOrCrSmWzmKI19MEauyn3SXYt
         NQww==
X-Gm-Message-State: AOJu0YwN++KEoFU+Kq4DRk4gxJGqvXgcNyEoi+uWERU7lvBTiurbCus/
	izCKlD2atImPu65NufPbZUhTE6aSswgsEJSfmd/EdPFJsIVZxybvo6xa9Zm8qFwdrh88qIoRM1x
	If6i7OLXW/M0ZjwfCbyW5QxU1AfD9iksM5aw=
X-Google-Smtp-Source: AGHT+IHlOKlIlXAYmLw6Ly6TIRCOkRvMVkmUdbQgdBZILYMopNOfny3Znyln9ByneRGeRV5LEtQqtyY+/PYbXCxWdoU=
X-Received: by 2002:a25:2e07:0:b0:dd1:3909:bdd with SMTP id
 3f1490d57ef6-df7722667a0mr10329240276.65.1716895562611; Tue, 28 May 2024
 04:26:02 -0700 (PDT)
MIME-Version: 1.0
From: saman ghaderi <saman381ghaderi@gmail.com>
Date: Tue, 28 May 2024 13:59:03 +0330
Message-ID: <CAFheeUN2R3TCKtyOByT+StNS_z7gsgA7ceRURHpd+ZJckALBrQ@mail.gmail.com>
Subject: =?UTF-8?B?U2VjdG9yINux27QgKDB4MEUpIFszOF0gcndpIDMzIDM5IDMwIDMzIDBBIDBBIEQ4IEFBIA==?=
	=?UTF-8?B?RDggQTcgRDggQjEgREIgOEMgRDggQUUgfDM5MDPikIrikIouLi4uLi4uLi4ufCBbMzldIHJ3aSAyMCBE?=
	=?UTF-8?B?OCBBNyBEOSA4NiBEOCBBQSBEOSA4MiBEOCBBNyBEOSA4NCAyMCAzQSAzMSB84pCgLi4uLi4uLi4uLi4u?=
	=?UTF-8?B?4pCgOjF8IFszQV0gcndpIDM0IDMwIDMyIDJGIDMwIDM1IDJGIDMyIDM5IDBBIDBBIOKQii4uLi4ufCBb?=
	=?UTF-8?B?M0JdIFdYVyBEMzpGNzpEMzpGNzpEMzpGNyA3RjowNzo4OCBYWDpYWDpYWDpYWDpYWDpYWCBQdWJsaWMg?=
	=?UTF-8?B?TkRFRiBrZXkgKHVua25vd24ga2V5KSBTZWN0b3Ig27HbtSAoMHgwRikgWzNDXSByd2kgQTcgRDkgODYg?=
	=?UTF-8?B?MjAgRDggQTcgRDkgODYgRDggQUEgRDkgODIgRDggQTcgRDkgODQgfC4uLuKQoC4uLi4uLi4uLi4uLnwg?=
	=?UTF-8?B?WzNEXSByd2kgM0EgMzAgMzkgM0EgMzQgMzQgRkUgMDAgMDAgMDAgMDAgMDAgMDAgMDAgMDAgMDAgfDow?=
	=?UTF-8?B?OTo0NC7ikIDikIDikIDikIDikIDikIDikIDikIDikIB8IFszRV0gcndpIDAwIDAwIDAwIDAwIDAwIDAw?=
	=?UTF-8?B?IDAwIDAwIDAwIDAwIDAwIDAwIDAwIDAwIDAwIDAwIHzikIDikIDikIDikIDikIDikIDikIDikIDikIA=?=
	=?UTF-8?B?4pCA4pCA4pCA4pCA4pCA4pCA4pCAfCBbM0ZdIFdYVyBEMzpGNzpEMzpGNzpEMzpGNyA3RjowNzo4OCA0?=
	=?UTF-8?B?MCBYWDpYWDpYWDpYWDpYWDpYWCBQdWJsaWMgTkRFRiBrZXkgKHVua25vd24ga2V5KSDYr9ix2LPYp9mF?=
	=?UTF-8?B?2KfZhtmHICjYtNin2b7YsdqpKSDYqNin2YbaqSDYqtis2KfYsdiqINi12KfYrdioINit2LPYp9ioOtiy?=
	=?UTF-8?B?2YfYsdmHINiy2YXbjNmGINm+2LHYr9in2LIg2qnYr9mF2YTbjDogMDA0NDAzNjM2MSDYtNmF2KfYsdmH?=
	=?UTF-8?B?INit2LPYp9ioOjI3NzkyMzU2NCBbMzhdIHJ3aSAzMyAzOSAzMCAzMyAwQSAwQSBEOCBBQSBEOCBBNyBE?=
	=?UTF-8?B?OCBCMSBEQiA4QyBEOCBBRSB8MzkwM+KQiuKQii4uLi4uLi4uLi58IFszOV0=?=
To: postmaster <postmaster@accountprotection.microsoft.com>
Content-Type: multipart/alternative; boundary="00000000000020467e061981e6c8"
Return-Path: saman381ghaderi@gmail.com
X-EOPAttributedMessage: 2
X-EOPTenantAttributedMessage: 5ba90553-c2cd-460e-b5fd-ab93ad9155c7:2
X-MS-TrafficTypeDiagnostic:
	CO1PEPF000042AA:EE_|MN6PR16MB5430:EE_|CH1PEPF0000AD74:EE_|SA0PR16MB3776:EE_|BL02EPF0001A107:EE_|PH0PR16MB4947:EE_
X-MS-Office365-Filtering-Correlation-Id: 1f9464a1-b090-4037-6e9f-08dc7f08f835
X-Microsoft-Antispam-Untrusted: BCL:0;ARA:13230031|7093399003;
X-Microsoft-Antispam-Message-Info-Original: =?us-ascii?Q?4s29TEBj26CygDL9qfm/FUACq6L7SLVnLJWaH47TgY9gB8JEHOcDYK4SfiFV?=
 =?us-ascii?Q?58T1Zo1UrfIwnsiIRTP0ToewGT701sa5CRaqueVnmhQcHh2dGSPZBRmJTtr0?=
 =?us-ascii?Q?SaRxcjHIEH5sEZMS5qpBLQCrQvtzDpv9gWcOlYdIorCbIh3ShGq9zzLo0/wW?=
 =?us-ascii?Q?ww6B7LBqhQu077X7IWwQFNgg4qjx1L6A/wzZEPoW0F2HI+DHoME1qEjVoKT/?=
 =?us-ascii?Q?/vhpFGp39KkAQOa4PTx0U3IUfsoDzcQgj5I6SPmtQbnebggJ6xTgvM3p6Db+?=
 =?us-ascii?Q?Ax4dIKZI5z/SdxpLSaG4HlGXDw0mWbJbvacVDpxVMCG+oo9Y6YnME5MF1Ozk?=
 =?us-ascii?Q?5rTfsyCx9UcXgqbf/lXHBW9cZBeg9bQSEmLX/yWn092xmQ9ssnPv8X/6nXD2?=
 =?us-ascii?Q?IK8ssMLj3TgK6NnoHiWn792nSTnTc2wOMUzjwmkjOHAWAx/4H3ktCKapFzIU?=
 =?us-ascii?Q?PgkMnAUQ2XJ8etuDW/itCsF0LtV4wB0SE+KnBOyNAijViJNz7ijpfXxf3W1v?=
 =?us-ascii?Q?2r+q5glWDjt9kAZPZFUD0gbSFkeBVP7uc/R/5puzG9GyhHLMo7W1w1OkrNEX?=
 =?us-ascii?Q?9xObnNMW4pS1SeG0htsec/s7xIFc9Ya8w0O7ZSQFh0vHmPD5A2kCs6p2AwoQ?=
 =?us-ascii?Q?xuCZyj96Ryjw/TrV3tfjV5wjTdGlQMO7msAk6iVWG/cFYTYVTn2eUfDGxJzd?=
 =?us-ascii?Q?jQVGsxx/Cpb+Ifjs4hPzB11udiFSvz/F3bp07Bfip3SLMdj+XDtwg6zhFfiy?=
 =?us-ascii?Q?5wslkdZ2pVoeLJ/D0bG+vMl2WSxNwKKHLATkthuoUARgZW1elmd5nbj2FxWJ?=
 =?us-ascii?Q?q7iPaHeUjxqpgd5kfaM69r0pJeFhEj1Xb8QV+tQOcazuv+aKrPzBJmm+9iuO?=
 =?us-ascii?Q?qelvSGAhANT7iDy4bR+4BFZbGzCDl+39xuYzOA5GhAKTx2HgPtbiypAKL/Gy?=
 =?us-ascii?Q?2YxEyiizd1rCjX+g2ZGxGT1/vfmlXmwhaRWBqXHxVjQXI5gnkRUQfPKRXYmZ?=
 =?us-ascii?Q?VJLpGIl7DTBqrZArPrGvpCg+pioFV51Grmyx+AyY3lSk4P5l5zaeES/OyW3i?=
 =?us-ascii?Q?ZD8C8QsdqcJ8DuCsYik7fPHA41mNz4xtpIBt48GxlypTCMRxyTW9o36W1K3V?=
 =?us-ascii?Q?aReLLsMELuJb2GkX/Q+U1zXO94mNqSu3ungP4eNgG6B2aU54ZPeWdtub3Hcn?=
 =?us-ascii?Q?Ze2HErG9AsI9lJ+1L1Hs7vg+2GfEYZ4UnziL7WIGTv8m4A2+2m8MOIEC2asZ?=
 =?us-ascii?Q?PT0rQEuxgQyv+jn7ECEnxd5H+o1KPZPqAWqxOoB7swQGotgyx/KdCSLwdCfr?=
 =?us-ascii?Q?NMOK8W461ZZuLN6VcOV2DsmBhWWu8KtfeBA4hy0atCqCY5+7Mnl7hSsPuG3W?=
 =?us-ascii?Q?lSOQO85gM6cgAtU+AiJjYwb+osX4rqWpk9Tbrua/S95jldjZuncV2mM/ZiIg?=
 =?us-ascii?Q?Ka7Tiw7O4pvNeMGshS0whxCCHzNY2pASwelQ90uBLt1aDysJZODG+z2vHIDh?=
 =?us-ascii?Q?IqAi1CtdnJPx3c6OTMY4Xv+nwXNkzpEUdg9/WOw4V/dy5bEuEG7GggzV0pk6?=
 =?us-ascii?Q?vDZThbaHTYl/J+hB2ZMVpGeguQFVxv0YZ+dxiOPtaOSoBBVzUAZLz67ISb8P?=
 =?us-ascii?Q?PgSrMIoOLD1TdvQU+PHQhZl06uMNvAz39RRfvPQSs3y4oivgzamWfGbDTYqj?=
 =?us-ascii?Q?W7Qv+QouAUZuusREN4oLYvyjKEoDF+tXPtCO4gUfGhONVOPzbwoe/zU+FJCi?=
 =?us-ascii?Q?HIB5d4ySSg=3D=3D?=
X-Forefront-Antispam-Report-Untrusted: CIP:209.85.219.174;CTRY:US;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:mail-yb1-f174.google.com;PTR:mail-yb1-f174.google.com;CAT:NONE;SFS:(13230031)(7093399003);DIR:INB;
X-ExternalRecipientOutboundConnectors: 5ba90553-c2cd-460e-b5fd-ab93ad9155c7
X-MS-Exchange-Transport-CrossTenantHeadersStamped: MN6PR16MB5430
X-MS-Exchange-Transport-CrossTenantHeadersStripped: CH1PEPF0000AD74.namprd04.prod.outlook.com
X-MS-Exchange-Transport-CrossTenantHeadersPromoted: CH1PEPF0000AD74.namprd04.prod.outlook.com
X-MS-Office365-Filtering-Correlation-Id-Prvs: a137b264-104b-4e07-203e-08dc7f08f5c8
X-Microsoft-Antispam-Untrusted: BCL:0;ARA:13230031|2040899004|7093399003|35042699013;
X-Microsoft-Antispam-Message-Info-Original: =?us-ascii?Q?IJ64f00dDp5qBPS28c+wmqpeNxRVTU7RhzWmZ1RS5tjqRCHb8iwWLp/cMKW4?=
 =?us-ascii?Q?+nmmnKwRaOWhC2Uc5HutRfxYjFKn/APjv9RQ4Sd30Q8Cd8S/urbzPlLA2dT+?=
 =?us-ascii?Q?9aPsKXK5AaC+HF1RKeLCAy7bgSUFpBqwoDHWsylu9rfB2KBvEEhXMj8atPKm?=
 =?us-ascii?Q?HucHjWw5N2geByJVf6RRLBTQybE0Xbou/DcWN7FjeIiOPlnqAlRHB25emMW2?=
 =?us-ascii?Q?VqXscDJeLCKT0IOllWvrE6n+wt881UrBU/9cIUPkqzqzTYElgjq3Bp5e4K42?=
 =?us-ascii?Q?mtcRic5da36t2w8wrFaS45iwK80+WArvwkqAM/Vn/XIh4+HZwewIbtExaDS/?=
 =?us-ascii?Q?HiZXAQ/vBgzw849Jrsb0eCvWq5VOZFiSZYZ7L2mL+A60b5UFRW1xIXPMW/Sc?=
 =?us-ascii?Q?As6MjUymoORhSSVJhQJt/kNo6dc9L8ahUlXTljS6U2KFD9rnDqFzMDOxXcX+?=
 =?us-ascii?Q?tpOsXVaC4d5INMlfmSHyvm0f1yBey3F/CenQy6qALH8VrRUx5O5ffhvFWjLU?=
 =?us-ascii?Q?Wyfnybtp5tPYJXP98UIWLJSKSx0pctz38MYT7ZbT/aYdMeq2fWuWhRY8Oix+?=
 =?us-ascii?Q?OIKI78uTBZSjGX1gpHcv1PD+MNw+ZCWepEt6TORuw10/3E1F4JWsbFrQ4NeD?=
 =?us-ascii?Q?DzLOYeygtekNApTkr1P8349GAoVZgQp8Oh7nugCkVlEmmzIgqftH+I9lCZUc?=
 =?us-ascii?Q?KDJs03BeESP47lKYEhvtSXZN2yw+AwyGAfLi+RwwRIX3eaS/MqkFJKVnY4mg?=
 =?us-ascii?Q?jFExF76BuwICI0nu2Ylv1LXi4d9rnaBqTyFyHmZRblSyfMoqX63d7PFf/IDc?=
 =?us-ascii?Q?gNRodWKbIb4kaigReJwICnBPhkFOMDbjU1rT+AFFtP2n951/dYsb0Zl7HzMo?=
 =?us-ascii?Q?xBKf9pjNtdg0nS37xv5xdi0JwhZh8DacBLWU/co7VWKv71vdDJp5f00xTSDN?=
 =?us-ascii?Q?KNGQjeWBUOEZ0TLjzeXN/iIYz2vlVWxt2NAnu4XTdpcPqd72Gy7VUROgOsE/?=
 =?us-ascii?Q?LOYzXWBIuo34Obm1nBFfnkGAzjvqSKY/KDQmbOuNoAUZ7P7qB8TkFJPPdHZh?=
 =?us-ascii?Q?M9dCNpV/mmFk2X6aMOy+T2pczdEWLr6QWdvVvK3NrtWsoZA8bQ698x070bAi?=
 =?us-ascii?Q?j3l2UUA2kFV44fwOBsc8GG+mEhNR8bI2zvAD1rQ1BjRl4SZ/mcLprw3chWPV?=
 =?us-ascii?Q?i9COB+ZXkKZU02AL1Yk1nwYkSl1fu24FZfZ9lEfv7nId6muXYvCIAD42wOgM?=
 =?us-ascii?Q?DNHFqSbZb2Nnw6g2tHBknaddLxc6C6AvnHmfClLi9GOPGU9JwcqpsJt13FRh?=
 =?us-ascii?Q?NJ2+BrjIhLAfJrQZRNzBi5L/HlslX/EggvI/dxg3Fiimu0Occ9GjsEJqrFlU?=
 =?us-ascii?Q?dGZSvoUapRLUie63n9v+hLE88hh+MbIxm63kUBE3O0wS35jl2utXmUBc4B/0?=
 =?us-ascii?Q?C9TGMDbfBpQKxyXZ8iwZc9X+gldTomyeu+O1GtlMwkZp8NgiReIAAHvg+MTi?=
 =?us-ascii?Q?+gVldcxcCTA9c5SK08YbWMC4ZIjYuQ9ESMHqQN9pIMoKaH0Bgx/aYncQ9m8i?=
 =?us-ascii?Q?DGXtp6HsM1kYaWn2IKdTD/IpIOA/qqtJoAS8+jwQhPDHhIxCqXizJtdstryX?=
 =?us-ascii?Q?/8/jLxFk49k6bMqHnW0BVZmAO9to0OuZVbLLy+aPjsUrg/xCr3skINaWOqD1?=
 =?us-ascii?Q?GWT1OPxxPY5hSZXaSMg9tHoi/GlWi4gTwYHdTB2uMkBPWS9QNS0Kjf7Gz8z0?=
 =?us-ascii?Q?myeEQIR2ig=3D=3D?=
X-Forefront-Antispam-Report-Untrusted: CIP:104.47.58.101;CTRY:US;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:NAM10-DM6-obe.outbound.protection.outlook.com;PTR:mail-dm6nam10lp2101.outbound.protection.outlook.com;CAT:NONE;SFS:(13230031)(2040899004)(7093399003)(35042699013);DIR:INB;
X-MS-Exchange-Transport-CrossTenantHeadersStamped: SA0PR16MB3776
X-MS-Exchange-Transport-CrossTenantHeadersStripped: BL02EPF0001A107.namprd05.prod.outlook.com
X-MS-Exchange-Transport-CrossTenantHeadersPromoted: BL02EPF0001A107.namprd05.prod.outlook.com
X-MS-PublicTrafficType: Email
X-MS-Office365-Filtering-Correlation-Id-Prvs:
	bebe7207-b457-4e17-01b8-08dc7f08f740
X-Microsoft-Antispam: BCL:0;ARA:13230031|2040899004|7093399003|35042699013;
X-Microsoft-Antispam-Message-Info:
	=?us-ascii?Q?kd81Zm2pR7kEdF/9GfLZ69YnVMl0WOUvmt4UxnwdxtB4PS1sa9tTjXuX1fH5?=
 =?us-ascii?Q?ni0m4oi1i0fy+ONCy89q17EM/bnwFRxg4Pc589iEaJMoGMCWCnwKTsZ4+JEA?=
 =?us-ascii?Q?Idikv4JMCZ2DvLPpJSuPAiTNf3LolY4N+WCetHCKv0VoR0+Z3E08d6Bvlkd8?=
 =?us-ascii?Q?HMHdoGE040uUhJAPNT6CIE4A7O1r4foU7KBj1c7L0tlrxW9NxN/4ZLlU0Pce?=
 =?us-ascii?Q?ECqT5gd30uiYmfiP4xuwK2K8D2/0Ixh/UVy2LfdRjRPlzIJ9tMLeGRyHrQ9b?=
 =?us-ascii?Q?EO2E0vvxtnlX2zcw+YFSXV6duWijsNJPwWWhaic+SdcEbafLmS+q8ocZ2Aow?=
 =?us-ascii?Q?yv1xE4W66355GCdT1KiwCOeL1HEqP/CfZiVr4bRHFI2KDrwq51qHetCGlKeh?=
 =?us-ascii?Q?gXQB8u40r/B13aD4S8KtxTBh6j5UuFpIcq3iICbR/V2fxP3Gq3xifC7JMJGG?=
 =?us-ascii?Q?mYf9CWWM7SLxhmJZvbV0e/WUndarFt5ddOtHWf7pGB4KqFabXpcezj6PGRlh?=
 =?us-ascii?Q?aHTxlaiQlIMq4GuZLYwavrS+Syi25ZXTcJtKwSmrndE2uvy5MFfJy8oR41v/?=
 =?us-ascii?Q?dZLkEjjCvPbvNipOgZTK8rOs/9BcNVdLVPekqqEk91Jijp1GN7JxePgsfkdZ?=
 =?us-ascii?Q?M49LpzRYzv+e3ufaK8z6b4Akiqo3fklFvwm1InapdC5K3XOMeaKlCxgr9UV+?=
 =?us-ascii?Q?ymoB/o5zUauLmbrYk4hb26GNlCQuKF45mRHn8eAB/kdt1vOCwiw7Y2lrNjmz?=
 =?us-ascii?Q?w6BP/mVYSPgQESGcb5pJJjdX/HnDN20mI/awR2Y9+gDH7OrwnNR8wGdNHKoJ?=
 =?us-ascii?Q?frTQ9BQEJX1vc2xcZbDqJgvdwFAMB1OylbkWeAY4BNv7IdgnQKeUwPXNPbJt?=
 =?us-ascii?Q?mxDokUpPkjeZJvs6/g2zy3tdiDHViSapT+ieC981/fcdc/b/7yQQ0JT7cGqV?=
 =?us-ascii?Q?zvNARYo+TgH7VfybRLhyIEUj2AzC/GD9Z2x+1jcwOirffQg3EpFyWab+qe62?=
 =?us-ascii?Q?j0rRXZk+hNeioaaINPEAfr+VA2H9ERYHFnd4ybdVLh07Wmt/hEG/idDFqw3c?=
 =?us-ascii?Q?OcgRI5YDv5DTuU+q4kGgKwbwn0ZYOCS2W3mhr/Ybh/izSw4GNLCY07tY2jeZ?=
 =?us-ascii?Q?GtIsrtBEashALBztwwxLSZvvPKP5sAvYzjPnmDOJ/Nyrgjmm3GtOvUytIpho?=
 =?us-ascii?Q?29k+9UiXXDbAr/a0nkB7ZDHIwBCJ8g5roYoO1CRUDohXo4fkVws1n1uHdd/W?=
 =?us-ascii?Q?OSAChXaUi265w5AtRwoHaKufx+WsWHJugCGMiklKrdPInltpyO7K6aK606c/?=
 =?us-ascii?Q?URk66gjb1GHFaC2vRrp1t4Kc0TZuhMECn7ZnEobszicHDZTLLw9CdbNxpTW6?=
 =?us-ascii?Q?NvCOD4n9OoAbjs3uHWLn0iO6zSjRGZCsKoLLHIHTMjKDaYgMO9gX38qHpfXi?=
 =?us-ascii?Q?pJOuADEsmoPWL/7F2oDq0B4XCoskTmBX45+MBDAJZI0N8dMJQ0K/eQg2zAZC?=
 =?us-ascii?Q?vUBgU5Z5KZkDxIbaGZWixL/YFsf/FzaCQdxZCEskpHXt9atxMR36JUOu33zg?=
 =?us-ascii?Q?Hdk6KZfYWLdOnIZQjUhVsdEOns3pUFQugbhGxxxlprPbkOivqPeP0ONS3aKn?=
 =?us-ascii?Q?wHJbz67hwiJDBcqy8IVOkpn+t3qi7MD6gQFuM1dHmBWA1FAlovVRkOwElNED?=
 =?us-ascii?Q?4J+Yu/I8izL0mc4hTzimm/2B2UstE9dNd4hYwK2uler00MBROohQEUBwtAUu?=
 =?us-ascii?Q?fG04ZUeT6g=3D=3D?=
X-Forefront-Antispam-Report:
	CIP:104.47.56.41;CTRY:US;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:NAM02-DM3-obe.outbound.protection.outlook.com;PTR:mail-dm3nam02lp2041.outbound.protection.outlook.com;CAT:NONE;SFS:(13230031)(2040899004)(7093399003)(35042699013);DIR:INB;
X-OriginatorOrg: accountprotection.microsoft.com
X-MS-Exchange-CrossTenant-OriginalArrivalTime: 28 May 2024 11:26:07.9078
 (UTC)
X-MS-Exchange-CrossTenant-Network-Message-Id: 1f9464a1-b090-4037-6e9f-08dc7f08f835
X-MS-Exchange-CrossTenant-Id: 5ba90553-c2cd-460e-b5fd-ab93ad9155c7
X-MS-Exchange-CrossTenant-AuthSource:
	BL02EPF0001A107.namprd05.prod.outlook.com
X-MS-Exchange-CrossTenant-AuthAs: Anonymous
X-MS-Exchange-CrossTenant-FromEntityHeader: Internet
X-MS-Exchange-Transport-CrossTenantHeadersStamped: PH0PR16MB4947
Resolving Conflict through Matrimony, an Old Model for Our Times. Congress, Take Note
No views


To Live Again Tomorrow - The Gift that Only Comes Through Pain
2 views


A Grouse of a Chance with Perseid
2 views


Jack London on Time and Aging
9 views


I Shave with Occam's Razor
462 views


My Lantern - Short
11 views


Garden of Children
4 views


Wake Walking
17 views


Conducting the Cath Lab Symphony
17 views


Bike Ride
<texte>
{{TEXTE}}
</texte>

Résume ce texte en 3 phrases, en évitant tout jargon technique :
import {stackn,rcross, sail, heart, stack, show, quarter_turn_right, quarter_turn_left} from "rune";


#1 CREATING A NEW FUNCTION
function turn_upside_down(rune) {
    return quarter_turn_right(quarter_turn_right(rune));
}

show (turn_upside_down(heart));

***show is a function--> brackets required.

#2 STACK FUNCTION (for only 2 runes, stacks vertically)
show (stack(heart,sail)); 

2A: stacking more than 2--> Apply stack multiple times
show (stack(heart, stack(heart, heart)));
/SIDE BY SIDE with STACK/

2B: Stacking something n times
import {stackn} from "rune";
show (stackn (5, heart));

#3 Side by Side
function beside (rune1, rune2) {
    return (quarter_turn_right(stack(quarter_turn_left(rune2), quarter_turn_left(rune1))));
}

show (beside (heart, heart));

#4 RECTANGULAR QULITING
const my_quilt = (stackn(7,(quarter_turn_left(stackn(5, quarter_turn_right(heart))))));

show(my_quilt);
function quilt (n , m , rune) {
    return 
}

#5 Creating a function for rectangular quilting (abstraction)

function quilt (n , m , rune) {
    return stackn(m , 
        quarter_turn_left(
            stackn(n, quarter_turn_right(
                rune))));
}

show (quilt(10, 10, heart));

#6 MAKE CROSS FUNCTION
import {turn_upside_down, beside} from "rune";


function make_cross(rune) {
    return beside (stack(quarter_turn_right(rune), rune), stack(turn_upside_down(rune), quarter_turn_left(rune)));
}

show(make_cross(make_cross(make_cross(make_cross(make_cross(rcross))))));

/Basically, the make_cross function multiplies the "set" by 2x on each side (l and b) every time you use it, e.g.: 1,2,4,8,16/

possible to apply make cross functions many times
since it is a transformation.
#include <iostream>
#include <vector>

int main() {
    std::vector<int> V = {1, 5, 4, 33, 0};

    // Display number of values stored in V
    std::cout << "V has " << std::ssize(V) << " elements.\n";
}
private bool _jumpToConsume;
        private bool _bufferedJumpUsable;
        private bool _endedJumpEarly;
        private bool _coyoteUsable;
        private float _timeJumpWasPressed;

        private bool HasBufferedJump => _bufferedJumpUsable && _time < _timeJumpWasPressed + _stats.JumpBuffer;
        private bool CanUseCoyote => _coyoteUsable && !_grounded && _time < _frameLeftGrounded + _stats.CoyoteTime;

        private void HandleJump()
        {
            if (!_endedJumpEarly && !_grounded && !_frameInput.JumpHeld && _rb.velocity.y > 0) _endedJumpEarly = true;

            if (!_jumpToConsume && !HasBufferedJump) return;

            if (_grounded || CanUseCoyote) ExecuteJump();

            _jumpToConsume = false;
        }

        private void ExecuteJump()
        {
            _endedJumpEarly = false;
            _timeJumpWasPressed = 0;
            _bufferedJumpUsable = false;
            _coyoteUsable = false;
            _frameVelocity.y = _stats.JumpPower;
            Jumped?.Invoke();
        }
add_filter( 'woocommerce_product_tabs', 'custom_tab' );
function custom_tab( $tabs ) {	
	// Adds the new tab
	$tabs['test_tab'] = array(
		'title' 	=> __( 'Measurement charts', 'woocommerce' ),
		'priority' 	=> 50,
		'callback' 	=> 'custom_tab_content'
	);
	return $tabs;
}
function custom_tab_content() {

	// The new tab content

	echo '<h2>Measurement charts</h2>';
	echo '<p>Lorem ipsum dolor sit amet consectetur adipiscing elit ultricies convallis volutpat, placerat proin scelerisque eget velit tellus at nibh risus. </p>';
	
}
add_filter( 'woocommerce_product_tabs', 'woo_reorder_tabs', 98 );
function woo_reorder_tabs( $tabs ) {

	$tabs['reviews']['priority'] = 5;			// Reviews first
	$tabs['description']['priority'] = 10;			// Description second
	$tabs['additional_information']['priority'] = 15;	// Additional information third

	return $tabs;
}
add_filter( 'woocommerce_product_tabs', 'woo_remove_product_tabs', 98 );

function woo_remove_product_tabs( $tabs ) {

    unset( $tabs['description'] );      	// Remove the description tab
    unset( $tabs['reviews'] ); 			// Remove the reviews tab
    unset( $tabs['additional_information'] );  	// Remove the additional information tab

    return $tabs;
}
add_filter( 'woocommerce_product_tabs', 'woo_rename_tabs', 98 );
function woo_rename_tabs( $tabs ) {

	$tabs['description']['title'] = __( 'More Information' );		// Rename the description tab
	$tabs['reviews']['title'] = __( 'Ratings' );				// Rename the reviews tab
	$tabs['additional_information']['title'] = __( 'Product Data' );	// Rename the additional information tab

	return $tabs;

}
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.DependencyInjection;
using System;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using av_motion_api.Data; // Adjust the namespace to match your project
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Options;
using Microsoft.Data.SqlClient;
using av_motion_api.Models;

namespace av_motion_api.Services
{
    public class OrderStatusUpdater : IHostedService, IDisposable
    {
        private Timer _timer;
        private readonly IServiceProvider _serviceProvider;
        private readonly IOptionsMonitor<OverdueSettings> _settings;

        public OrderStatusUpdater(IServiceProvider serviceProvider, IOptionsMonitor<OverdueSettings> settings)
        {
            _serviceProvider = serviceProvider;
            _settings = settings;
        }

        public Task StartAsync(CancellationToken cancellationToken)
        {
            ScheduleOrderStatusUpdate();
            _settings.OnChange(settings => ScheduleOrderStatusUpdate());
            return Task.CompletedTask;
        }

        private void ScheduleOrderStatusUpdate()
        {
            var overdueTimeValue = _settings.CurrentValue.OverdueTimeValue;
            var overdueTimeUnit = _settings.CurrentValue.OverdueTimeUnit;

            if (string.IsNullOrEmpty(overdueTimeUnit))
            {
                // Log error or warning here
                Console.WriteLine("OverdueTimeUnit is null or empty.");
            }

            var interval = GetTimeSpan(overdueTimeValue, overdueTimeUnit);
            _timer?.Dispose();
            _timer = new Timer(UpdateOrderStatuses, null, TimeSpan.Zero, interval);
        }

        private void UpdateOrderStatuses(object state)
        {
            using (var scope = _serviceProvider.CreateScope())
            {
                var context = scope.ServiceProvider.GetRequiredService<AppDbContext>();

                // Calculate the overdue threshold time
                var overdueThreshold = DateTime.UtcNow.Subtract(GetTimeSpan(_settings.CurrentValue.OverdueTimeValue, _settings.CurrentValue.OverdueTimeUnit));

                var connection = context.Database.GetDbConnection();
                if (connection.State != System.Data.ConnectionState.Open)
                {
                    connection.Open();
                }

                using (var command = connection.CreateCommand())
                {
                    command.CommandText = "UpdateOrderStatuses";
                    command.CommandType = System.Data.CommandType.StoredProcedure;

                    // Add the required parameters
                    command.Parameters.Add(new SqlParameter("@OverdueTimeValue", _settings.CurrentValue.OverdueTimeValue));
                    command.Parameters.Add(new SqlParameter("@OverdueTimeUnit", _settings.CurrentValue.OverdueTimeUnit));

                    // Execute the stored procedure
                    command.ExecuteNonQuery();
                }
            }
        }

        private TimeSpan GetTimeSpan(int value, string unit)
        {
            if (string.IsNullOrEmpty(unit))
            {
                throw new ArgumentNullException(nameof(unit), "Unit cannot be null or empty.");
            }

            return unit.ToLower() switch
            {
                "minutes" => TimeSpan.FromMinutes(value),
                "hours" => TimeSpan.FromHours(value),
                "days" => TimeSpan.FromDays(value),
                "weeks" => TimeSpan.FromDays(value * 7),
                "months" => TimeSpan.FromDays(value * 30), // Approximation
                "years" => TimeSpan.FromDays(value * 365), // Approximation
                _ => TimeSpan.FromMinutes(value),
            };
        }

        public Task StopAsync(CancellationToken cancellationToken)
        {
            _timer?.Change(Timeout.Infinite, 0);
            return Task.CompletedTask;
        }

        public void Dispose()
        {
            _timer?.Dispose();
        }
    }
}
if(or(isnotblank(Filters[Title]), isnotblank(Filters[From...]), isnotblank(Filters[To...])),
sum(select(Expenses[Total Paid], and(
    if(isnotblank(any(Filters[Title])), and([Title] = any(Filters[Title]), [Title]=[_THISROW].[UID]), [Title]=[_THISROW].[UID]),
    if(isnotblank(any(Filters[From...])), [Date] >= any(Filters[From...]), true),
    if(isnotblank(any(Filters[To...])), [Date] <= any(Filters[To...]), true)
))),
sum(select(Expenses[Total Paid], [Title]=[_THISROW].[UID])))
# Add this reg file to Post-Setup (Before logon):

Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\ContentDeliveryManager]
; BingWeather, Candy Crush and etc.
"SubscribedContent-314559Enabled"=dword:00000000

; My People Suggested Apps
"SubscribedContent-314563Enabled"=dword:00000000

; Occasionally show suggestions in Start
"SubscribedContent-338388Enabled"=dword:00000000
- name: ls -a via ssh
  uses: garygrossgarten/github-action-ssh@release
  with:
    command: ls -a
    host: ${{ secrets.HOST }}
    username: garygrossgarten
    passphrase: ${{ secrets.PASSPHRASE }}
    privateKey: ${{ secrets.PRIVATE_KEY}}
name: Sync Fork

on:
  schedule:
    - cron: '*/30 * * * *' # every 30 minutes
  workflow_dispatch: # on button click

jobs:
  sync:

    runs-on: ubuntu-latest

    steps:
      - uses: tgymnich/fork-sync@v2.0
        with:
          token: ${{ secrets.PERSONAL_TOKEN }}
          owner: llvm
          base: master
          head: master
# Add 'root' label to any root file changes
# Quotation marks are required for the leading asterisk
root:
- changed-files:
  - any-glob-to-any-file: '*'

# Add 'AnyChange' label to any changes within the entire repository
AnyChange:
- changed-files:
  - any-glob-to-any-file: '**'

# Add 'Documentation' label to any changes within 'docs' folder or any subfolders
Documentation:
- changed-files:
  - any-glob-to-any-file: docs/**

# Add 'Documentation' label to any file changes within 'docs' folder
Documentation:
- changed-files:
  - any-glob-to-any-file: docs/*

# Add 'Documentation' label to any file changes within 'docs' or 'guides' folders
Documentation:
- changed-files:
  - any-glob-to-any-file:
    - docs/*
    - guides/*

## Equivalent of the above mentioned configuration using another syntax
Documentation:
- changed-files:
  - any-glob-to-any-file: ['docs/*', 'guides/*']

# Add 'Documentation' label to any change to .md files within the entire repository 
Documentation:
- changed-files:
  - any-glob-to-any-file: '**/*.md'

# Add 'source' label to any change to src files within the source dir EXCEPT for the docs sub-folder
source:
- all:
  - changed-files:
    - any-glob-to-any-file: 'src/**/*'
    - all-globs-to-all-files: '!src/docs/*'

# Add 'feature' label to any PR where the head branch name starts with `feature` or has a `feature` section in the name
feature:
 - head-branch: ['^feature', 'feature']

# Add 'release' label to any PR that is opened against the `main` branch
release:
 - base-branch: 'main'
jobs:
  run:
    runs-on: ${{ matrix.operating-system }}
    strategy:
      matrix:
        operating-system: ['ubuntu-latest', 'windows-latest', 'macos-latest']
        php-versions: ['8.1', '8.2', '8.3']
        phpunit-versions: ['latest']
        include:
          - operating-system: 'ubuntu-latest'
            php-versions: '8.0'
            phpunit-versions: 9
    steps:
    - name: Setup PHP
      uses: shivammathur/setup-php@v2
      with:
        php-version: ${{ matrix.php-versions }}
        extensions: mbstring, intl
        ini-values: post_max_size=256M, max_execution_time=180
        coverage: xdebug
        tools: php-cs-fixer, phpunit:${{ matrix.phpunit-versions }}
      env:
        GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
  {
    "op": "CustomVal",
    "searchfor": "MAX_CONSECUTIVE_LOW_TEMPERATURE_ERROR_ALLOWED",
    "value": "10",
    "comment": "Fixes MINTEMP issue caused by unstable temperature readings"
  }
jobs:
  build:
    runs-on: ubuntu-latest
    strategy:
      matrix:
        node: [ 14, 16, 18 ]
    name: Node ${{ matrix.node }} sample
    steps:
      - uses: actions/checkout@v4
      - name: Setup node
        uses: actions/setup-node@v4
        with:
          node-version: ${{ matrix.node }}
      - run: npm ci
      - run: npm test
# This workflow uses actions that are not certified by GitHub.
# They are provided by a third-party and are governed by
# separate terms of service, privacy policy, and support
# documentation.

# GitHub recommends pinning actions to a commit SHA.
# To get a newer version, you will need to update the SHA.
# You can also reference a tag or branch, but the action may change without warning.

on:
  push:
    branches:
      - main

env:
  AZURE_WEBAPP_NAME: MY_WEBAPP_NAME   # set this to your application's name
  AZURE_WEBAPP_PACKAGE_PATH: '.'      # set this to the path to your web app project, defaults to the repository root
  NODE_VERSION: '14.x'                # set this to the node version to use

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v4

    - name: Set up Node.js
      uses: actions/setup-node@v4
      with:
        node-version: ${{ env.NODE_VERSION }}
        cache: 'npm'

    - name: npm install, build, and test
      run: |
        npm install
        npm run build --if-present
        npm run test --if-present
    - name: Upload artifact for deployment job
      uses: actions/upload-artifact@v4
      with:
        name: node-app
        path: .

  deploy:
    runs-on: ubuntu-latest
    needs: build
    environment:
      name: 'production'
      url: ${{ steps.deploy-to-webapp.outputs.webapp-url }}

    steps:
    - name: Download artifact from build job
      uses: actions/download-artifact@v4
      with:
        name: node-app

    - name: 'Deploy to Azure WebApp'
      id: deploy-to-webapp
      uses: azure/webapps-deploy@85270a1854658d167ab239bce43949edb336fa7c
      with:
        app-name: ${{ env.AZURE_WEBAPP_NAME }}
        publish-profile: ${{ secrets.AZURE_WEBAPP_PUBLISH_PROFILE }}
        package: ${{ env.AZURE_WEBAPP_PACKAGE_PATH }}
name: Python package

on: [push]

jobs:
  build:

    runs-on: ubuntu-latest
    strategy:
      matrix:
        python-version: ["pypy3.9", "pypy3.10", "3.9", "3.10", "3.11", "3.12"]

    steps:
      - uses: actions/checkout@v4
      - name: Set up Python ${{ matrix.python-version }}
        uses: actions/setup-python@v5
        with:
          python-version: ${{ matrix.python-version }}
      # You can test your matrix by printing the current Python version
      - name: Display Python version
        run: python -c "import sys; print(sys.version)"
if (!function_exists('dd')) {
    function dd(...$vars)
    {
        // ألوان مختلفة ومتناغمة
        $colors = [
            '#ff9999', '#66b3ff', '#99ff99', '#ffcc99', '#c2c2f0',
            '#ffb3e6', '#c2f0c2', '#ffccff', '#ffb3b3', '#c2c2c2'
        ];
        $colorCount = count($colors);
        
        // الحصول على معلومات إضافية
        $backtrace = debug_backtrace();
        $debugInfo = [
            'line' => $backtrace[0]['line'],
            'file' => $backtrace[0]['file'],
            'function' => $backtrace[1]['function'] ?? 'N/A',
            'request' => $_REQUEST,
            'session' => $_SESSION ?? []
        ];

        // عرض المعلومات الافتراضية إذا لم يتم تمرير أي متغيرات
        if (empty($vars)) {
            $vars[] = [
                'file' => $debugInfo['file'],
                'line' => $debugInfo['line'],
                'function' => $debugInfo['function'],
                'request' => $debugInfo['request'],
                'session' => $debugInfo['session'],
            ];
        }

        echo '<div style="font-family: Arial, sans-serif; line-height: 1.5;">';
        
        foreach ($vars as $index => $var) {
            // حدد اللون بناءً على الفهرس
            $color = $colors[$index % $colorCount];
            
            echo '<div style="background-color: ' . $color . '; padding: 10px; border-radius: 5px; margin-bottom: 10px; color: #fff;">';
            
            // عنوان البلوك
            echo '<strong>Breakpoint (' . $debugInfo['file'] . ' on line ' . $debugInfo['line'] . ') ---> Function: ' . $debugInfo['function'] . '</strong><br>';
            echo '<strong>Request Data:</strong><br>';
            echo '<pre>' . json_encode($debugInfo['request'], JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES) . '</pre>';
            echo '<strong>Session Data:</strong><br>';
            echo '<pre>' . json_encode($debugInfo['session'], JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES) . '</pre>';
            
            // عرض المتغيرات
            echo '<strong>Variable ' . ($index + 1) . ':</strong><br>';
            if (is_array($var) || is_object($var)) {
                echo '<pre>' . json_encode($var, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES) . '</pre>';
            } elseif (is_bool($var) || is_null($var)) {
                var_dump($var);
            } else {
                echo htmlspecialchars($var, ENT_QUOTES, 'UTF-8');
            }
            
            echo '</div>';
        }
        
        echo '</div>';
        die(1);
    }
}
<?php
namespace App\Http\Controllers\Callback;

use App\Models\Gig;
use App\Models\User;
use App\Models\Order;
use Razorpay\Api\Api;
use App\Models\OrderItem;
use App\Models\GigUpgrade;
use Illuminate\Support\Str;
use App\Models\OrderInvoice;
use Illuminate\Http\Request;
use App\Models\DepositWebhook;
use App\Models\CheckoutWebhook;
use App\Models\OrderItemUpgrade;
use App\Models\DepositTransaction;
use App\Http\Controllers\Controller;
use Illuminate\Support\Facades\Http;
use App\Models\AutomaticPaymentGateway;
use App\Notifications\User\Buyer\OrderPlaced;
use App\Notifications\User\Seller\PendingOrder;

class RazorpayController extends Controller
{
    public $gateway = "razorpay";
    public $status  = "paid";
    public $settings;


    /**
     * Payment gateway callback
     *
     * @param Request $request
     * @return mixed
     */
    public function callback(Request $request)
    {
        try {
            
            // Get payment gateway settings
            $settings       = AutomaticPaymentGateway::where('slug', $this->gateway)
                                                     ->where('is_active', true)
                                                     ->firstOrFail();

            // Set settings
            $this->settings = $settings;

            // Get payment id
            $payment_id     = $request->get('payment_id');

            // Get order id
            $order_id       = $request->get('order_id');

            // Get signature
            $signature      = $request->get('signature');

            // Get action
            $action         = $request->get('action');

            // Check webhook event
            if ( $payment_id && $order_id && $signature ) {

                // Check if payment succeeded
                $response = $this->verify($payment_id, $order_id, $signature);

                // Check if payment succeeded
                if ( is_array($response) && $response['success'] === TRUE) {

                    // Check if deposit callback
                    if ($action === "D") {
                        
                        // Get saved webhook data in our database
                        $data = DepositWebhook::where('payment_id', $order_id)
                                                ->where('payment_method', $this->gateway)
                                                ->where('status', 'pending')
                                                ->firstOrFail();
        
                        // Handle deposit callback
                        $this->deposit($data->user_id, $data->amount, $order_id);

                        // Delete saved webhook data in our database
                        $data->delete();

                        // Redirecting
                        return $this->redirect('deposit');

                    }
    
                    // Check if checkout callback
                    if ($action === "G") {
                        
                        // Get saved webhook data in our database
                        $data = CheckoutWebhook::where('payment_id', $order_id)
                                                ->where('payment_method', $this->gateway)
                                                ->where('status', 'pending')
                                                ->firstOrFail();
    
                        // Get cart
                        $cart = $data->data['cart'];
    
                        // Get user
                        $user = User::where('id', $data->data['buyer_id'])->firstOrFail();
        
                        // Handle deposit callback
                        $this->checkout($cart, $user, $order_id);

                        // Delete saved webhook data in our database
                        $data->delete();

                        // Redirecting
                        return $this->redirect('gigs');
    
                    }

                }

            }

            // In case failed redirect to home page
            return redirect('/');

        } catch (\Throwable $th) {

            // Error
            throw $th;

        }
    }


    /**
     * Verify if payment succeeded
     *
     * @param string $id
     * @return array
     */
    private function verify($payment_id, $order_id, $signature)
    {
        try {

            // Get payment gateway keys
            $key_id        = $this->settings?->settings['key_id'];
            $key_secret    = $this->settings?->settings['key_secret'];

            // Set api
            $api           = new Api($key_id, $key_secret);

            // Let's verify first the signature
            $api->utility->verifyPaymentSignature([
                'razorpay_signature'  => $signature,
                'razorpay_payment_id' => $payment_id,
                'razorpay_order_id'   => $order_id
            ]);

            // Fetch this payment
            $fetch_payment = $api->payment->fetch($payment_id);

            // Check if payment authorized
            if ($fetch_payment->status === 'authorized') {
                
                // Let capture this payment
                $payment = $api->payment->fetch($payment_id)->capture([
                    'amount'   => $fetch_payment->amount,
                    'currency' => $fetch_payment->currency
                ]);

            } else if ($fetch_payment->status === 'captured') {
                
                // Set payment
                $payment = $fetch_payment;

            } else {

                // Payment failed
                return [
                    'success'  => false,
                    'message'  => __('messages.t_we_could_not_handle_ur_payment')
                ];

            }

            // Check if payment succeeded
            if ( $payment && $payment->status === 'captured' ) {
                
                // Done
                return [
                    'success'  => true,
                    'response' => $payment
                ];

            } else {

                // Failed
                return [
                    'success' => false,
                    'message' => __('messages.t_error_stripe_payment_failed')
                ];

            }

        } catch (\Throwable $th) {
            
            // Error
            return [
                'success' => false,
                'message' => __('messages.t_toast_something_went_wrong')
            ];

        }
    }


    /**
     * Deposit funds into user's account
     *
     * @param int $user_id
     * @param mixed $amount
     * @param string $payment_id
     * @return void
     */
    private function deposit($user_id, $amount, $payment_id)
    {
        try {
            
            // Set amount
            $amount                  = convertToNumber($amount);
            
            // Calculate fee from this amount
            $fee                     = convertToNumber($this->fee('deposit', $amount)); 

            // Make transaction
            $deposit                 = new DepositTransaction();
            $deposit->user_id        = $user_id;
            $deposit->transaction_id = $payment_id;
            $deposit->payment_method = $this->gateway;
            $deposit->amount_total   = $amount;
            $deposit->amount_fee     = $fee;
            $deposit->amount_net     = $amount - $fee;
            $deposit->currency       = $this->settings->currency;
            $deposit->exchange_rate  = $this->settings->exchange_rate;
            $deposit->status         = $this->status;
            $deposit->ip_address     = request()->ip();
            $deposit->save();

            // Get user
            $user                    = User::where('id', $user_id)->firstOrFail();

            // Add funds
            $user->balance_available = convertToNumber($user->balance_available) + convertToNumber($deposit->amount_net);
            $user->save();

            // Send  a notification
            $this->notification('deposit', $user);

        } catch (\Throwable $th) {

            // Error
            throw $th;

        }
    }


    /**
     * Checkout
     *
     * @param array $cart
     * @param object $user
     * @param string $payment_id
     * @return void
     */
    private function checkout($cart, $user, $payment_id)
    {
        try {

            // Set empty variables
            $subtotal = 0;
            $total    = 0;
            $tax      = 0;
            $fee      = 0;

            // Loop through items in cart
            foreach ($cart as $key => $item) {
                    
                // Add gig price to subtotal
                $subtotal += convertToNumber($item['gig']['price']) * convertToNumber($item['quantity']);

                // Check if item has upgrades
                $upgrades  = $item['upgrades'];

                // Loop through upgrades
                if ( isset($upgrades) && is_array($upgrades) && count($upgrades) ) {
                    
                    // Loop through upgrades
                    foreach ($upgrades as $j => $upgrade) {
                        
                        // Check if upgrade checked
                        if ( isset($upgrade['checked']) && $upgrade['checked'] == 1 ) {
                            
                            // Add upgrade price to subtotal
                            $subtotal += convertToNumber($upgrade['price']) * convertToNumber($item['quantity']);

                        }

                    }

                }

            }

            // Get commission settings
            $commission_settings = settings('commission');

            // Check if taxes enabled
            if ($commission_settings->enable_taxes) {
                
                // Check if type of taxes percentage
                if ($commission_settings->tax_type === 'percentage') {
                    
                    // Set tax amount
                    $tax       = convertToNumber(bcmul($subtotal, $commission_settings->tax_value) / 100);

                } else {
                    
                    // Set tax amount
                    $tax       = convertToNumber($commission_settings->tax_value);

                }

            }

            // Calculate payment gateway fee
            $fee                   = convertToNumber($this->fee( 'gigs', $subtotal ));
            
            // Calculate total price
            $total                 = $subtotal + $tax + $fee;
        
            // Get user billing address
            $billing_info          = $user->billing;

            // Set unique id for this order
            $uid                   = uid();

            // Get buyer id
            $buyer_id              = $user->id;

            // Save order
            $order                 = new Order();
            $order->uid            = $uid;
            $order->buyer_id       = $buyer_id;
            $order->total_value    = $total;
            $order->subtotal_value = $subtotal;
            $order->taxes_value    = $tax;
            $order->save();

            // Loop through items in cart
            foreach ($cart as $key => $item) {
                    
                // Get gig
                $gig = Gig::where('uid', $item['id'])->with('owner')->active()->first();

                // Check if gig exists
                if ($gig) {
                    
                    // Set quantity
                    $quantity        = isset($item['quantity']) ? convertToNumber($item['quantity']) : 1;

                    // Set gig upgrades
                    $upgrades        = isset($item['upgrades']) && is_array($item['upgrades']) && count($item['upgrades']) ? $item['upgrades'] : [];

                    // Set empty variable
                    $upgrades_amount = 0;

                    // Loop through upgrades
                    foreach ($upgrades as $index => $upgrade) {
                        
                        // Check if upgrade is selected
                        if ( isset($upgrade['checked']) && $upgrade['checked'] == 1 ) {
                            
                            $upgrades_amount += convertToNumber($upgrade['price']) * $quantity;

                        }

                    }

                    // Set item total price
                    $item_total = $upgrades_amount + ( convertToNumber($item['gig']['price']) * $quantity );

                    // Calculate commission first
                    if ($commission_settings->commission_from === 'orders') {
                        
                        // Check commission type
                        if ($commission_settings->commission_type === 'percentage') {
                            
                            // Calculate commission
                            $commission = convertToNumber($commission_settings->commission_value) * $item_total / 100;
    
                        } else {
    
                            // Fixed amount
                            $commission = convertToNumber($commission_settings->commission_value);
    
                        }

                    } else {
                        
                        // No commission
                        $commission = 0;

                    }

                    // Save order item
                    $order_item                         = new OrderItem();
                    $order_item->uid                    = uid();
                    $order_item->order_id               = $order->id;
                    $order_item->gig_id                 = $gig->id;
                    $order_item->owner_id               = $gig->user_id;
                    $order_item->quantity               = $quantity;
                    $order_item->has_upgrades           = count($upgrades) ? true : false;
                    $order_item->total_value            = $item_total;
                    $order_item->profit_value           = $item_total - $commission;
                    $order_item->commission_value       = $commission;
                    $order_item->save();

                    // Loop through upgrades again
                    foreach ($upgrades as $index => $value) {
                        
                        // Check if upgrade is selected
                        if ( isset($upgrade['checked']) && $upgrade['checked'] == 1 ) {
                        
                            // Get upgrade
                            $upgrade = GigUpgrade::where('uid', $value['id'])->where('gig_id', $gig->id)->first();
    
                            // Check if upgrade exists
                            if ($upgrade) {
                                
                                // Save item upgrade
                                $order_item_upgrade             = new OrderItemUpgrade();
                                $order_item_upgrade->item_id    = $order_item->id;
                                $order_item_upgrade->title      = $upgrade->title;
                                $order_item_upgrade->price      = $upgrade->price;
                                $order_item_upgrade->extra_days = $upgrade->extra_days;
                                $order_item_upgrade->save();
    
                            }

                        }
                        
                    }

                    // Update seller pending balance
                    $gig->owner()->update([
                        'balance_pending' => convertToNumber($gig->owner->balance_pending) + convertToNumber($order_item->profit_value)
                    ]);

                    // Increment orders in queue
                    $gig->increment('orders_in_queue');

                    // Order item placed successfully
                    // Let's notify the seller about new order
                    $gig->owner->notify( (new PendingOrder($order_item))->locale(config('app.locale')) );

                    // Check user's level
                    check_user_level($buyer_id);

                    // Send notification
                    notification([
                        'text'    => 't_u_received_new_order_seller',
                        'action'  => url('seller/orders/details', $order_item->uid),
                        'user_id' => $order_item->owner_id
                    ]);

                }

            }

            // Save invoice
            $invoice                 = new OrderInvoice();
            $invoice->order_id       = $order->id;
            $invoice->payment_method = $this->gateway;
            $invoice->payment_id     = $payment_id;
            $invoice->firstname      = $billing_info->firstname ?? $user->username;
            $invoice->lastname       = $billing_info->lastname ?? $user->username;
            $invoice->email          = $user->email;
            $invoice->company        = !empty($billing_info->company) ? clean($billing_info->company) : null;
            $invoice->address        = !empty($billing_info->address) ? clean($billing_info->address) : "NA";
            $invoice->status         = 'paid';
            $invoice->save();

            // Update balance
            $user->update([
                'balance_purchases' => convertToNumber($user->balance_purchases) + convertToNumber($total)
            ]);

            // Now everything succeeded
            // Let's empty the cart
            session()->forget('cart');

            // Now let's notify the buyer that his order has been placed
            $user->notify( (new OrderPlaced($order))->locale(config('app.locale')) );

        } catch (\Throwable $th) {
            
            // Error
            throw $th;

        }
    }


    /**
     * Calculate fee value
     *
     * @param string $type
     * @param mixed $amount
     * @return mixed
     */
    private function fee($type, $amount = null)
    {
        try {
            
            // Set amount for deposit
            $amount = convertToNumber($amount) * $this->settings?->exchange_rate / settings('currency')->exchange_rate;

            // Remove long decimal
            $amount = convertToNumber( number_format($amount, 2, '.', '') );

            // Check fee type
            switch ($type) {
    
                // Deposit
                case 'deposit':
    
                    // Get deposit fixed fee
                    if (isset($this->settings->fixed_fee['deposit'])) {
                        
                        // Set fixed fee
                        $fee_fixed = convertToNumber($this->settings->fixed_fee['deposit']);
    
                    } else {
    
                        // No fixed fee
                        $fee_fixed = 0;
    
                    }
    
                    // Get deposit percentage fee
                    if (isset($this->settings->percentage_fee['deposit'])) {
                        
                        // Set percentage fee
                        $fee_percentage = convertToNumber($this->settings->percentage_fee['deposit']);
    
                    } else {
    
                        // No percentage fee
                        $fee_percentage = 0;
    
                    }
    
                    // Calculate percentage of this amount 
                    $fee_percentage_amount = $this->exchange( $fee_percentage * $amount / 100, $this->settings->exchange_rate );

                    // Calculate exchange rate of this fixed fee
                    $fee_fixed_exchange    = $this->exchange( $fee_fixed,  $this->settings->exchange_rate);
                    
                    // Calculate fee value and visible text
                    if ($fee_fixed > 0 && $fee_percentage > 0) {
                        
                        // Calculate fee value
                        $fee_value = convertToNumber($fee_percentage_amount) + convertToNumber($fee_fixed_exchange);
    
                    } else if (!$fee_fixed && $fee_percentage > 0) {
                        
                        // Calculate fee value
                        $fee_value = convertToNumber($fee_percentage_amount);
    
                    } else if ($fee_fixed > 0 && !$fee_percentage) {
    
                        // Calculate fee value
                        $fee_value = convertToNumber($fee_fixed_exchange);
                        
                    } else if (!$fee_percentage && !$fee_fixed) {
                        
                        // Calculate fee value
                        $fee_value = 0;
    
                    }
                    
                    // Return fee value
                    return number_format($fee_value, 2, '.', '');
    
                break;

                // Gigs
                case 'gigs':

                    // Get gigs fixed fee
                    if (isset($this->settings->fixed_fee['gigs'])) {
                        
                        // Set fixed fee
                        $fee_fixed = convertToNumber($this->settings->fixed_fee['gigs']);
    
                    } else {
    
                        // No fixed fee
                        $fee_fixed = 0;
    
                    }
    
                    // Get gigs percentage fee
                    if (isset($this->settings->percentage_fee['gigs'])) {
                        
                        // Set percentage fee
                        $fee_percentage = convertToNumber($this->settings->percentage_fee['gigs']);
    
                    } else {
    
                        // No percentage fee
                        $fee_percentage = 0;
    
                    }
    
                    // Calculate percentage of this amount 
                    $fee_percentage_amount = $this->exchange( $fee_percentage * $amount / 100, $this->settings->exchange_rate );

                    // Calculate exchange rate of this fixed fee
                    $fee_fixed_exchange    = $this->exchange( $fee_fixed,  $this->settings->exchange_rate);
    
                    // Calculate fee value and visible text
                    if ($fee_fixed > 0 && $fee_percentage > 0) {
                        
                        // Calculate fee value
                        $fee_value = convertToNumber($fee_percentage_amount) + convertToNumber($fee_fixed_exchange);
    
                    } else if (!$fee_fixed && $fee_percentage > 0) {
                        
                        // Calculate fee value
                        $fee_value = convertToNumber($fee_percentage_amount);
    
                    } else if ($fee_fixed > 0 && !$fee_percentage) {
    
                        // Calculate fee value
                        $fee_value = convertToNumber($fee_fixed_exchange);
                        
                    } else if (!$fee_percentage && !$fee_fixed) {
                        
                        // Calculate fee value
                        $fee_value = 0;
    
                    }
    
                    // Return fee value
                    return $fee_value;

                break;
    
            }

        } catch (\Throwable $th) {
            
            // Something went wrong
            return 0;

        }
    }


    /**
     * Calculate exchange rate
     *
     * @param mixed $amount
     * @param mixed $exchange_rate
     * @param boolean $formatted
     * @param string $currency
     * @return mixed
     */
    private function exchange($amount, $exchange_rate, $formatted = false, $currency = null)
    {
        try {

            // Convert amount to number
            $amount                = convertToNumber($amount);

            // Get currency settings
            $currency_settings     = settings('currency');

            // Get default currency exchange rate
            $default_exchange_rate = convertToNumber($currency_settings->exchange_rate);

            // Get exchanged amount
            $exchanged_amount      = convertToNumber( $amount *  $default_exchange_rate / $exchange_rate );

            // Check if we have to return a formatted value
            if ($formatted) {
                
                return money( $exchanged_amount, $currency, true )->format();

            }

            // Return max deposit
            return convertToNumber(number_format( $exchanged_amount, 2, '.', '' ));

        } catch (\Throwable $th) {

            // Something went wrong
            return $amount;

        }
    }


    /**
     * Send a notification to user
     *
     * @param string $type
     * @param object $user
     * @return void
     */
    private function notification($type, $user)
    {
        try {
            
            // Check notification type
            switch ($type) {

                // Deposit funds
                case 'deposit':
                    


                break;

                // Gig checkout
                case 'gig':
                    
                    

                break;

                // Project payment
                case 'project':
                    
                    

                break;

                // Bid payment
                case 'bid':
                    
                    

                break;

            }

        } catch (\Throwable $th) {
            
            // Something went wrong
            return;

        }
    }


    /**
     * Redirecting
     *
     * @param string $type
     * @param string $status
     * @return void
     */
    private function redirect($type, $status = 'success')
    {
        // Check where to redirect
        switch ($type) {

            // Deposit history
            case 'deposit':
                
                // Check if payment succeeded
                if ($status === 'success') {
                    
                    // Redirect to deposit history page
                    return redirect('account/deposit/history')->with('success', __('messages.t_ur_transaction_has_completed'));

                } else if ($status === 'pending') {
                    
                    // Redirect to deposit history page
                    return redirect('account/deposit/history')->with('success', __('messages.t_mollie_payment_pending'));

                }
                

            break;

            // Gigs order
            case 'gigs':
                
                // Check if payment succeeded
                if ($status === 'success') {
                    
                    // Redirect to deposit history page
                    return redirect('account/orders')->with('success', __('messages.t_submit_ur_info_now_seller_start_order'));

                } else if ($status === 'pending') {
                    
                    // Redirect to deposit history page
                    return redirect('account/orders')->with('success', __('messages.t_mollie_payment_pending'));

                }

            break;

        }
    }
}
<?php
namespace App\Http\Controllers\Callback;

use App\Models\Gig;
use App\Models\User;
use App\Models\Order;
use App\Models\OrderItem;
use App\Models\GigUpgrade;
use App\Models\OrderInvoice;
use Illuminate\Http\Request;
use App\Models\DepositWebhook;
use App\Models\CheckoutWebhook;
use App\Models\OrderItemUpgrade;
use App\Models\DepositTransaction;
use App\Http\Controllers\Controller;
use Illuminate\Support\Facades\Http;
use App\Models\AutomaticPaymentGateway;
use App\Notifications\User\Buyer\OrderPlaced;
use App\Notifications\User\Seller\PendingOrder;

class PaymobPkController extends Controller
{
    public $gateway = "paymob-pk";
    public $status  = "paid";
    public $settings;


    /**
     * Payment gateway callback
     *
     * @param Request $request
     * @return mixed
     */
    public function callback(Request $request)
    {
        try {
            
            // Get payment gateway settings
            $settings       = AutomaticPaymentGateway::where('slug', $this->gateway)
                                                     ->where('is_active', true)
                                                     ->firstOrFail();

            // Set settings
            $this->settings = $settings;

            // Get transaction id
            $transaction_id = $request->get('id');

            // Check webhook event
            if ( $transaction_id ) {

                // Check if payment succeeded
                $response = $this->verify($transaction_id);
                
                // Check if payment succeeded
                if ( is_array($response) && $response['success'] === TRUE) {
                    
                    // Get action
                    $action   = $response['response']['obj']['order']['shipping_data']['shipping_method'];

                    // Check if deposit callback
                    if ( isset($action) && $action === "D" ) {
                        
                        // Get saved webhook data in our database
                        $data = DepositWebhook::where('payment_id', $transaction_id)
                                                ->where('payment_method', $this->gateway)
                                                ->where('status', 'pending')
                                                ->firstOrFail();
        
                        // Handle deposit callback
                        $this->deposit($data->user_id, $data->amount, $transaction_id);

                        // Delete saved webhook data in our database
                        $data->delete();

                        // Redirecting
                        return $this->redirect('deposit');

                    }
    
                    // Check if checkout callback
                    if ( isset($action) && $action === "G" ) {
                        
                        // Get saved webhook data in our database
                        $data = CheckoutWebhook::where('payment_id', $transaction_id)
                                                ->where('payment_method', $this->gateway)
                                                ->where('status', 'pending')
                                                ->firstOrFail();
    
                        // Get cart
                        $cart = $data->data['cart'];
    
                        // Get user
                        $user = User::where('id', $data->data['buyer_id'])->firstOrFail();
        
                        // Handle deposit callback
                        $this->checkout($cart, $user, $transaction_id);

                        // Delete saved webhook data in our database
                        $data->delete();

                        // Redirecting
                        return $this->redirect('gigs');
    
                    }

                }

            }

            // In case failed redirect to home page
            return redirect('/');

        } catch (\Throwable $th) {

            // Error
            throw $th;

        }
    }


    /**
     * Verify if payment succeeded
     *
     * @param string $id
     * @return array
     */
    private function verify($id)
    {
        try {

            // Get auth token
            $auth    = Http::acceptJson()->post('https://pakistan.paymob.com/api/auth/tokens', [
                                            'api_key' => $this->settings?->settings['api_key'],
                                        ])->json();

            // Check if token is set
            if (isset($auth['token'])) {

                // Get payment details
                $payment = Http::withToken($auth['token'])
                                ->get("https://pakistan.paymob.com/api/acceptance/transactions/$id")
                                ->json();

                // Check if payment succeeded
                if ( is_array($payment) && isset($payment['obj']['success']) && $payment['obj']['success'] == true ) {
                    
                    // Done
                    return [
                        'success'  => true,
                        'response' => $payment
                    ];

                } else {

                    // Failed
                    return [
                        'success' => false,
                        'message' => __('messages.t_error_stripe_payment_failed')
                    ];

                }

            } else {

                // Failed
                return [
                    'success' => false,
                    'message' => __('messages.t_error_stripe_payment_failed')
                ];

            }

        } catch (\Throwable $th) {
            
            // Error
            return [
                'success' => false,
                'message' => __('messages.t_toast_something_went_wrong')
            ];

        }
    }


    /**
     * Deposit funds into user's account
     *
     * @param int $user_id
     * @param mixed $amount
     * @param string $payment_id
     * @return void
     */
    private function deposit($user_id, $amount, $payment_id)
    {
        try {
            
            // Set amount
            $amount                  = convertToNumber($amount);
            
            // Calculate fee from this amount
            $fee                     = convertToNumber($this->fee('deposit', $amount)); 

            // Make transaction
            $deposit                 = new DepositTransaction();
            $deposit->user_id        = $user_id;
            $deposit->transaction_id = $payment_id;
            $deposit->payment_method = $this->gateway;
            $deposit->amount_total   = $amount;
            $deposit->amount_fee     = $fee;
            $deposit->amount_net     = $amount - $fee;
            $deposit->currency       = $this->settings->currency;
            $deposit->exchange_rate  = $this->settings->exchange_rate;
            $deposit->status         = $this->status;
            $deposit->ip_address     = request()->ip();
            $deposit->save();

            // Get user
            $user                    = User::where('id', $user_id)->firstOrFail();

            // Add funds
            $user->balance_available = convertToNumber($user->balance_available) + convertToNumber($deposit->amount_net);
            $user->save();

            // Send  a notification
            $this->notification('deposit', $user);

        } catch (\Throwable $th) {

            // Error
            throw $th;

        }
    }


    /**
     * Checkout
     *
     * @param array $cart
     * @param object $user
     * @param string $payment_id
     * @return void
     */
    private function checkout($cart, $user, $payment_id)
    {
        try {

            // Set empty variables
            $subtotal = 0;
            $total    = 0;
            $tax      = 0;
            $fee      = 0;

            // Loop through items in cart
            foreach ($cart as $key => $item) {
                    
                // Add gig price to subtotal
                $subtotal += convertToNumber($item['gig']['price']) * convertToNumber($item['quantity']);

                // Check if item has upgrades
                $upgrades  = $item['upgrades'];

                // Loop through upgrades
                if ( isset($upgrades) && is_array($upgrades) && count($upgrades) ) {
                    
                    // Loop through upgrades
                    foreach ($upgrades as $j => $upgrade) {
                        
                        // Check if upgrade checked
                        if ( isset($upgrade['checked']) && $upgrade['checked'] == 1 ) {
                            
                            // Add upgrade price to subtotal
                            $subtotal += convertToNumber($upgrade['price']) * convertToNumber($item['quantity']);

                        }

                    }

                }

            }

            // Get commission settings
            $commission_settings = settings('commission');

            // Check if taxes enabled
            if ($commission_settings->enable_taxes) {
                
                // Check if type of taxes percentage
                if ($commission_settings->tax_type === 'percentage') {
                    
                    // Set tax amount
                    $tax       = convertToNumber(bcmul($subtotal, $commission_settings->tax_value) / 100);

                } else {
                    
                    // Set tax amount
                    $tax       = convertToNumber($commission_settings->tax_value);

                }

            }

            // Calculate payment gateway fee
            $fee                   = convertToNumber($this->fee( 'gigs', $subtotal ));
            
            // Calculate total price
            $total                 = $subtotal + $tax + $fee;
        
            // Get user billing address
            $billing_info          = $user->billing;

            // Set unique id for this order
            $uid                   = uid();

            // Get buyer id
            $buyer_id              = $user->id;

            // Save order
            $order                 = new Order();
            $order->uid            = $uid;
            $order->buyer_id       = $buyer_id;
            $order->total_value    = $total;
            $order->subtotal_value = $subtotal;
            $order->taxes_value    = $tax;
            $order->save();

            // Loop through items in cart
            foreach ($cart as $key => $item) {
                    
                // Get gig
                $gig = Gig::where('uid', $item['id'])->with('owner')->active()->first();

                // Check if gig exists
                if ($gig) {
                    
                    // Set quantity
                    $quantity        = isset($item['quantity']) ? convertToNumber($item['quantity']) : 1;

                    // Set gig upgrades
                    $upgrades        = isset($item['upgrades']) && is_array($item['upgrades']) && count($item['upgrades']) ? $item['upgrades'] : [];

                    // Set empty variable
                    $upgrades_amount = 0;

                    // Loop through upgrades
                    foreach ($upgrades as $index => $upgrade) {
                        
                        // Check if upgrade is selected
                        if ( isset($upgrade['checked']) && $upgrade['checked'] == 1 ) {
                            
                            $upgrades_amount += convertToNumber($upgrade['price']) * $quantity;

                        }

                    }

                    // Set item total price
                    $item_total = $upgrades_amount + ( convertToNumber($item['gig']['price']) * $quantity );

                    // Calculate commission first
                    if ($commission_settings->commission_from === 'orders') {
                        
                        // Check commission type
                        if ($commission_settings->commission_type === 'percentage') {
                            
                            // Calculate commission
                            $commission = convertToNumber($commission_settings->commission_value) * $item_total / 100;
    
                        } else {
    
                            // Fixed amount
                            $commission = convertToNumber($commission_settings->commission_value);
    
                        }

                    } else {
                        
                        // No commission
                        $commission = 0;

                    }

                    // Save order item
                    $order_item                         = new OrderItem();
                    $order_item->uid                    = uid();
                    $order_item->order_id               = $order->id;
                    $order_item->gig_id                 = $gig->id;
                    $order_item->owner_id               = $gig->user_id;
                    $order_item->quantity               = $quantity;
                    $order_item->has_upgrades           = count($upgrades) ? true : false;
                    $order_item->total_value            = $item_total;
                    $order_item->profit_value           = $item_total - $commission;
                    $order_item->commission_value       = $commission;
                    $order_item->save();

                    // Loop through upgrades again
                    foreach ($upgrades as $index => $value) {
                        
                        // Check if upgrade is selected
                        if ( isset($upgrade['checked']) && $upgrade['checked'] == 1 ) {
                        
                            // Get upgrade
                            $upgrade = GigUpgrade::where('uid', $value['id'])->where('gig_id', $gig->id)->first();
    
                            // Check if upgrade exists
                            if ($upgrade) {
                                
                                // Save item upgrade
                                $order_item_upgrade             = new OrderItemUpgrade();
                                $order_item_upgrade->item_id    = $order_item->id;
                                $order_item_upgrade->title      = $upgrade->title;
                                $order_item_upgrade->price      = $upgrade->price;
                                $order_item_upgrade->extra_days = $upgrade->extra_days;
                                $order_item_upgrade->save();
    
                            }

                        }
                        
                    }

                    // Update seller pending balance
                    $gig->owner()->update([
                        'balance_pending' => convertToNumber($gig->owner->balance_pending) + convertToNumber($order_item->profit_value)
                    ]);

                    // Increment orders in queue
                    $gig->increment('orders_in_queue');

                    // Order item placed successfully
                    // Let's notify the seller about new order
                    $gig->owner->notify( (new PendingOrder($order_item))->locale(config('app.locale')) );

                    // Check user's level
                    check_user_level($buyer_id);

                    // Send notification
                    notification([
                        'text'    => 't_u_received_new_order_seller',
                        'action'  => url('seller/orders/details', $order_item->uid),
                        'user_id' => $order_item->owner_id
                    ]);

                }

            }

            // Save invoice
            $invoice                 = new OrderInvoice();
            $invoice->order_id       = $order->id;
            $invoice->payment_method = $this->gateway;
            $invoice->payment_id     = $payment_id;
            $invoice->firstname      = $billing_info->firstname ?? $user->username;
            $invoice->lastname       = $billing_info->lastname ?? $user->username;
            $invoice->email          = $user->email;
            $invoice->company        = !empty($billing_info->company) ? clean($billing_info->company) : null;
            $invoice->address        = !empty($billing_info->address) ? clean($billing_info->address) : "NA";
            $invoice->status         = 'paid';
            $invoice->save();

            // Update balance
            $user->update([
                'balance_purchases' => convertToNumber($user->balance_purchases) + convertToNumber($total)
            ]);

            // Now everything succeeded
            // Let's empty the cart
            session()->forget('cart');

            // Now let's notify the buyer that his order has been placed
            $user->notify( (new OrderPlaced($order))->locale(config('app.locale')) );

        } catch (\Throwable $th) {
            
            // Error
            throw $th;

        }
    }


    /**
     * Calculate fee value
     *
     * @param string $type
     * @param mixed $amount
     * @return mixed
     */
    private function fee($type, $amount = null)
    {
        try {
            
            // Set amount for deposit
            $amount = convertToNumber($amount) * $this->settings?->exchange_rate / settings('currency')->exchange_rate;

            // Remove long decimal
            $amount = convertToNumber( number_format($amount, 2, '.', '') );

            // Check fee type
            switch ($type) {
    
                // Deposit
                case 'deposit':
    
                    // Get deposit fixed fee
                    if (isset($this->settings->fixed_fee['deposit'])) {
                        
                        // Set fixed fee
                        $fee_fixed = convertToNumber($this->settings->fixed_fee['deposit']);
    
                    } else {
    
                        // No fixed fee
                        $fee_fixed = 0;
    
                    }
    
                    // Get deposit percentage fee
                    if (isset($this->settings->percentage_fee['deposit'])) {
                        
                        // Set percentage fee
                        $fee_percentage = convertToNumber($this->settings->percentage_fee['deposit']);
    
                    } else {
    
                        // No percentage fee
                        $fee_percentage = 0;
    
                    }
    
                    // Calculate percentage of this amount 
                    $fee_percentage_amount = $this->exchange( $fee_percentage * $amount / 100, $this->settings->exchange_rate );

                    // Calculate exchange rate of this fixed fee
                    $fee_fixed_exchange    = $this->exchange( $fee_fixed,  $this->settings->exchange_rate);
                    
                    // Calculate fee value and visible text
                    if ($fee_fixed > 0 && $fee_percentage > 0) {
                        
                        // Calculate fee value
                        $fee_value = convertToNumber($fee_percentage_amount) + convertToNumber($fee_fixed_exchange);
    
                    } else if (!$fee_fixed && $fee_percentage > 0) {
                        
                        // Calculate fee value
                        $fee_value = convertToNumber($fee_percentage_amount);
    
                    } else if ($fee_fixed > 0 && !$fee_percentage) {
    
                        // Calculate fee value
                        $fee_value = convertToNumber($fee_fixed_exchange);
                        
                    } else if (!$fee_percentage && !$fee_fixed) {
                        
                        // Calculate fee value
                        $fee_value = 0;
    
                    }
                    
                    // Return fee value
                    return number_format($fee_value, 2, '.', '');
    
                break;

                // Gigs
                case 'gigs':

                    // Get gigs fixed fee
                    if (isset($this->settings->fixed_fee['gigs'])) {
                        
                        // Set fixed fee
                        $fee_fixed = convertToNumber($this->settings->fixed_fee['gigs']);
    
                    } else {
    
                        // No fixed fee
                        $fee_fixed = 0;
    
                    }
    
                    // Get gigs percentage fee
                    if (isset($this->settings->percentage_fee['gigs'])) {
                        
                        // Set percentage fee
                        $fee_percentage = convertToNumber($this->settings->percentage_fee['gigs']);
    
                    } else {
    
                        // No percentage fee
                        $fee_percentage = 0;
    
                    }
    
                    // Calculate percentage of this amount 
                    $fee_percentage_amount = $this->exchange( $fee_percentage * $amount / 100, $this->settings->exchange_rate );

                    // Calculate exchange rate of this fixed fee
                    $fee_fixed_exchange    = $this->exchange( $fee_fixed,  $this->settings->exchange_rate);
    
                    // Calculate fee value and visible text
                    if ($fee_fixed > 0 && $fee_percentage > 0) {
                        
                        // Calculate fee value
                        $fee_value = convertToNumber($fee_percentage_amount) + convertToNumber($fee_fixed_exchange);
    
                    } else if (!$fee_fixed && $fee_percentage > 0) {
                        
                        // Calculate fee value
                        $fee_value = convertToNumber($fee_percentage_amount);
    
                    } else if ($fee_fixed > 0 && !$fee_percentage) {
    
                        // Calculate fee value
                        $fee_value = convertToNumber($fee_fixed_exchange);
                        
                    } else if (!$fee_percentage && !$fee_fixed) {
                        
                        // Calculate fee value
                        $fee_value = 0;
    
                    }
    
                    // Return fee value
                    return $fee_value;

                break;
    
            }

        } catch (\Throwable $th) {
            
            // Something went wrong
            return 0;

        }
    }


    /**
     * Calculate exchange rate
     *
     * @param mixed $amount
     * @param mixed $exchange_rate
     * @param boolean $formatted
     * @param string $currency
     * @return mixed
     */
    private function exchange($amount, $exchange_rate, $formatted = false, $currency = null)
    {
        try {

            // Convert amount to number
            $amount                = convertToNumber($amount);

            // Get currency settings
            $currency_settings     = settings('currency');

            // Get default currency exchange rate
            $default_exchange_rate = convertToNumber($currency_settings->exchange_rate);

            // Get exchanged amount
            $exchanged_amount      = convertToNumber( $amount *  $default_exchange_rate / $exchange_rate );

            // Check if we have to return a formatted value
            if ($formatted) {
                
                return money( $exchanged_amount, $currency, true )->format();

            }

            // Return max deposit
            return convertToNumber(number_format( $exchanged_amount, 2, '.', '' ));

        } catch (\Throwable $th) {

            // Something went wrong
            return $amount;

        }
    }


    /**
     * Send a notification to user
     *
     * @param string $type
     * @param object $user
     * @return void
     */
    private function notification($type, $user)
    {
        try {
            
            // Check notification type
            switch ($type) {

                // Deposit funds
                case 'deposit':
                    


                break;

                // Gig checkout
                case 'gig':
                    
                    

                break;

                // Project payment
                case 'project':
                    
                    

                break;

                // Bid payment
                case 'bid':
                    
                    

                break;

            }

        } catch (\Throwable $th) {
            
            // Something went wrong
            return;

        }
    }


    /**
     * Redirecting
     *
     * @param string $type
     * @param string $status
     * @return void
     */
    private function redirect($type, $status = 'success')
    {
        // Check where to redirect
        switch ($type) {

            // Deposit history
            case 'deposit':
                
                // Check if payment succeeded
                if ($status === 'success') {
                    
                    // Redirect to deposit history page
                    return redirect('account/deposit/history')->with('success', __('messages.t_ur_transaction_has_completed'));

                } else if ($status === 'pending') {
                    
                    // Redirect to deposit history page
                    return redirect('account/deposit/history')->with('success', __('messages.t_mollie_payment_pending'));

                }
                

            break;

            // Gigs order
            case 'gigs':
                
                // Check if payment succeeded
                if ($status === 'success') {
                    
                    // Redirect to deposit history page
                    return redirect('account/orders')->with('success', __('messages.t_submit_ur_info_now_seller_start_order'));

                } else if ($status === 'pending') {
                    
                    // Redirect to deposit history page
                    return redirect('account/orders')->with('success', __('messages.t_mollie_payment_pending'));

                }

            break;

        }
    }
}
<?php
namespace App\Http\Controllers\Callback;

use App\Models\Gig;
use App\Models\User;
use App\Models\Order;
use App\Models\OrderItem;
use App\Models\GigUpgrade;
use Illuminate\Support\Str;
use App\Models\OrderInvoice;
use Illuminate\Http\Request;
use App\Models\DepositWebhook;
use App\Models\CheckoutWebhook;
use App\Models\OrderItemUpgrade;
use App\Models\DepositTransaction;
use App\Http\Controllers\Controller;
use Illuminate\Support\Facades\Http;
use App\Models\AutomaticPaymentGateway;
use App\Notifications\User\Buyer\OrderPlaced;
use App\Notifications\User\Seller\PendingOrder;

class FlutterwaveController extends Controller
{
    public $gateway = "flutterwave";
    public $status  = "paid";
    public $settings;


    /**
     * Payment gateway callback
     *
     * @param Request $request
     * @return mixed
     */
    public function callback(Request $request)
    {
        try {
            
            // Get payment gateway settings
            $settings       = AutomaticPaymentGateway::where('slug', $this->gateway)
                                                     ->where('is_active', true)
                                                     ->firstOrFail();

            // Set settings
            $this->settings = $settings;

            // Get transaction id
            $transaction_id = $request->get('transaction_id');

            // Check webhook event
            if ( $transaction_id ) {

                // Check if payment succeeded
                $response = $this->verify($transaction_id);
                
                // Check if payment succeeded
                if ( is_array($response) && $response['success'] === TRUE) {
                    
                    // Get order id
                    $order_id = $response['response']['data']['tx_ref'];

                    // Check if deposit callback
                    if (Str::startsWith($order_id, "DD")) {
                        
                        // Get saved webhook data in our database
                        $data = DepositWebhook::where('payment_id', $order_id)
                                                ->where('payment_method', $this->gateway)
                                                ->where('status', 'pending')
                                                ->firstOrFail();
        
                        // Handle deposit callback
                        $this->deposit($data->user_id, $data->amount, $order_id);

                        // Delete saved webhook data in our database
                        $data->delete();

                        // Redirecting
                        return $this->redirect('deposit');

                    }
    
                    // Check if checkout callback
                    if (Str::startsWith($order_id, "GG")) {
                        
                        // Get saved webhook data in our database
                        $data = CheckoutWebhook::where('payment_id', $order_id)
                                                ->where('payment_method', $this->gateway)
                                                ->where('status', 'pending')
                                                ->firstOrFail();
    
                        // Get cart
                        $cart = $data->data['cart'];
    
                        // Get user
                        $user = User::where('id', $data->data['buyer_id'])->firstOrFail();
        
                        // Handle deposit callback
                        $this->checkout($cart, $user, $order_id);

                        // Delete saved webhook data in our database
                        $data->delete();

                        // Redirecting
                        return $this->redirect('gigs');
    
                    }

                }

            }

            // In case failed redirect to home page
            return redirect('/');

        } catch (\Throwable $th) {

            // Error
            throw $th;

        }
    }


    /**
     * Verify if payment succeeded
     *
     * @param string $id
     * @return array
     */
    private function verify($id)
    {
        try {

            // Get payment gateway keys
            $secret_key = $this->settings?->settings['secret_key'];

            $response   = Http::withHeaders([
                                    'Authorization' => 'Bearer ' . $secret_key,
                                    'Accept'        => 'application/json',
                                ])->get("https://api.flutterwave.com/v3/transactions/$id/verify")->json();

            // Check if payment succeeded
            if ( is_array($response) && $response['status'] === 'success' ) {
                
                // Done
                return [
                    'success'  => true,
                    'response' => $response
                ];

            } else {

                // Failed
                return [
                    'success' => false,
                    'message' => __('messages.t_error_stripe_payment_failed')
                ];

            }

        } catch (\Throwable $th) {
            
            // Error
            return [
                'success' => false,
                'message' => __('messages.t_toast_something_went_wrong')
            ];

        }
    }


    /**
     * Deposit funds into user's account
     *
     * @param int $user_id
     * @param mixed $amount
     * @param string $payment_id
     * @return void
     */
    private function deposit($user_id, $amount, $payment_id)
    {
        try {
            
            // Set amount
            $amount                  = convertToNumber($amount);
            
            // Calculate fee from this amount
            $fee                     = convertToNumber($this->fee('deposit', $amount)); 

            // Make transaction
            $deposit                 = new DepositTransaction();
            $deposit->user_id        = $user_id;
            $deposit->transaction_id = $payment_id;
            $deposit->payment_method = $this->gateway;
            $deposit->amount_total   = $amount;
            $deposit->amount_fee     = $fee;
            $deposit->amount_net     = $amount - $fee;
            $deposit->currency       = $this->settings->currency;
            $deposit->exchange_rate  = $this->settings->exchange_rate;
            $deposit->status         = $this->status;
            $deposit->ip_address     = request()->ip();
            $deposit->save();

            // Get user
            $user                    = User::where('id', $user_id)->firstOrFail();

            // Add funds
            $user->balance_available = convertToNumber($user->balance_available) + convertToNumber($deposit->amount_net);
            $user->save();

            // Send  a notification
            $this->notification('deposit', $user);

        } catch (\Throwable $th) {

            // Error
            throw $th;

        }
    }


    /**
     * Checkout
     *
     * @param array $cart
     * @param object $user
     * @param string $payment_id
     * @return void
     */
    private function checkout($cart, $user, $payment_id)
    {
        try {

            // Set empty variables
            $subtotal = 0;
            $total    = 0;
            $tax      = 0;
            $fee      = 0;

            // Loop through items in cart
            foreach ($cart as $key => $item) {
                    
                // Add gig price to subtotal
                $subtotal += convertToNumber($item['gig']['price']) * convertToNumber($item['quantity']);

                // Check if item has upgrades
                $upgrades  = $item['upgrades'];

                // Loop through upgrades
                if ( isset($upgrades) && is_array($upgrades) && count($upgrades) ) {
                    
                    // Loop through upgrades
                    foreach ($upgrades as $j => $upgrade) {
                        
                        // Check if upgrade checked
                        if ( isset($upgrade['checked']) && $upgrade['checked'] == 1 ) {
                            
                            // Add upgrade price to subtotal
                            $subtotal += convertToNumber($upgrade['price']) * convertToNumber($item['quantity']);

                        }

                    }

                }

            }

            // Get commission settings
            $commission_settings = settings('commission');

            // Check if taxes enabled
            if ($commission_settings->enable_taxes) {
                
                // Check if type of taxes percentage
                if ($commission_settings->tax_type === 'percentage') {
                    
                    // Set tax amount
                    $tax       = convertToNumber(bcmul($subtotal, $commission_settings->tax_value) / 100);

                } else {
                    
                    // Set tax amount
                    $tax       = convertToNumber($commission_settings->tax_value);

                }

            }

            // Calculate payment gateway fee
            $fee                   = convertToNumber($this->fee( 'gigs', $subtotal ));
            
            // Calculate total price
            $total                 = $subtotal + $tax + $fee;
        
            // Get user billing address
            $billing_info          = $user->billing;

            // Set unique id for this order
            $uid                   = uid();

            // Get buyer id
            $buyer_id              = $user->id;

            // Save order
            $order                 = new Order();
            $order->uid            = $uid;
            $order->buyer_id       = $buyer_id;
            $order->total_value    = $total;
            $order->subtotal_value = $subtotal;
            $order->taxes_value    = $tax;
            $order->save();

            // Loop through items in cart
            foreach ($cart as $key => $item) {
                    
                // Get gig
                $gig = Gig::where('uid', $item['id'])->with('owner')->active()->first();

                // Check if gig exists
                if ($gig) {
                    
                    // Set quantity
                    $quantity        = isset($item['quantity']) ? convertToNumber($item['quantity']) : 1;

                    // Set gig upgrades
                    $upgrades        = isset($item['upgrades']) && is_array($item['upgrades']) && count($item['upgrades']) ? $item['upgrades'] : [];

                    // Set empty variable
                    $upgrades_amount = 0;

                    // Loop through upgrades
                    foreach ($upgrades as $index => $upgrade) {
                        
                        // Check if upgrade is selected
                        if ( isset($upgrade['checked']) && $upgrade['checked'] == 1 ) {
                            
                            $upgrades_amount += convertToNumber($upgrade['price']) * $quantity;

                        }

                    }

                    // Set item total price
                    $item_total = $upgrades_amount + ( convertToNumber($item['gig']['price']) * $quantity );

                    // Calculate commission first
                    if ($commission_settings->commission_from === 'orders') {
                        
                        // Check commission type
                        if ($commission_settings->commission_type === 'percentage') {
                            
                            // Calculate commission
                            $commission = convertToNumber($commission_settings->commission_value) * $item_total / 100;
    
                        } else {
    
                            // Fixed amount
                            $commission = convertToNumber($commission_settings->commission_value);
    
                        }

                    } else {
                        
                        // No commission
                        $commission = 0;

                    }

                    // Save order item
                    $order_item                         = new OrderItem();
                    $order_item->uid                    = uid();
                    $order_item->order_id               = $order->id;
                    $order_item->gig_id                 = $gig->id;
                    $order_item->owner_id               = $gig->user_id;
                    $order_item->quantity               = $quantity;
                    $order_item->has_upgrades           = count($upgrades) ? true : false;
                    $order_item->total_value            = $item_total;
                    $order_item->profit_value           = $item_total - $commission;
                    $order_item->commission_value       = $commission;
                    $order_item->save();

                    // Loop through upgrades again
                    foreach ($upgrades as $index => $value) {
                        
                        // Check if upgrade is selected
                        if ( isset($upgrade['checked']) && $upgrade['checked'] == 1 ) {
                        
                            // Get upgrade
                            $upgrade = GigUpgrade::where('uid', $value['id'])->where('gig_id', $gig->id)->first();
    
                            // Check if upgrade exists
                            if ($upgrade) {
                                
                                // Save item upgrade
                                $order_item_upgrade             = new OrderItemUpgrade();
                                $order_item_upgrade->item_id    = $order_item->id;
                                $order_item_upgrade->title      = $upgrade->title;
                                $order_item_upgrade->price      = $upgrade->price;
                                $order_item_upgrade->extra_days = $upgrade->extra_days;
                                $order_item_upgrade->save();
    
                            }

                        }
                        
                    }

                    // Update seller pending balance
                    $gig->owner()->update([
                        'balance_pending' => convertToNumber($gig->owner->balance_pending) + convertToNumber($order_item->profit_value)
                    ]);

                    // Increment orders in queue
                    $gig->increment('orders_in_queue');

                    // Order item placed successfully
                    // Let's notify the seller about new order
                    $gig->owner->notify( (new PendingOrder($order_item))->locale(config('app.locale')) );

                    // Check user's level
                    check_user_level($buyer_id);

                    // Send notification
                    notification([
                        'text'    => 't_u_received_new_order_seller',
                        'action'  => url('seller/orders/details', $order_item->uid),
                        'user_id' => $order_item->owner_id
                    ]);

                }

            }

            // Save invoice
            $invoice                 = new OrderInvoice();
            $invoice->order_id       = $order->id;
            $invoice->payment_method = $this->gateway;
            $invoice->payment_id     = $payment_id;
            $invoice->firstname      = $billing_info->firstname ?? $user->username;
            $invoice->lastname       = $billing_info->lastname ?? $user->username;
            $invoice->email          = $user->email;
            $invoice->company        = !empty($billing_info->company) ? clean($billing_info->company) : null;
            $invoice->address        = !empty($billing_info->address) ? clean($billing_info->address) : "NA";
            $invoice->status         = 'paid';
            $invoice->save();

            // Update balance
            $user->update([
                'balance_purchases' => convertToNumber($user->balance_purchases) + convertToNumber($total)
            ]);

            // Now everything succeeded
            // Let's empty the cart
            session()->forget('cart');

            // Now let's notify the buyer that his order has been placed
            $user->notify( (new OrderPlaced($order))->locale(config('app.locale')) );

        } catch (\Throwable $th) {
            
            // Error
            throw $th;

        }
    }


    /**
     * Calculate fee value
     *
     * @param string $type
     * @param mixed $amount
     * @return mixed
     */
    private function fee($type, $amount = null)
    {
        try {
            
            // Set amount for deposit
            $amount = convertToNumber($amount) * $this->settings?->exchange_rate / settings('currency')->exchange_rate;

            // Remove long decimal
            $amount = convertToNumber( number_format($amount, 2, '.', '') );

            // Check fee type
            switch ($type) {
    
                // Deposit
                case 'deposit':
    
                    // Get deposit fixed fee
                    if (isset($this->settings->fixed_fee['deposit'])) {
                        
                        // Set fixed fee
                        $fee_fixed = convertToNumber($this->settings->fixed_fee['deposit']);
    
                    } else {
    
                        // No fixed fee
                        $fee_fixed = 0;
    
                    }
    
                    // Get deposit percentage fee
                    if (isset($this->settings->percentage_fee['deposit'])) {
                        
                        // Set percentage fee
                        $fee_percentage = convertToNumber($this->settings->percentage_fee['deposit']);
    
                    } else {
    
                        // No percentage fee
                        $fee_percentage = 0;
    
                    }
    
                    // Calculate percentage of this amount 
                    $fee_percentage_amount = $this->exchange( $fee_percentage * $amount / 100, $this->settings->exchange_rate );

                    // Calculate exchange rate of this fixed fee
                    $fee_fixed_exchange    = $this->exchange( $fee_fixed,  $this->settings->exchange_rate);
                    
                    // Calculate fee value and visible text
                    if ($fee_fixed > 0 && $fee_percentage > 0) {
                        
                        // Calculate fee value
                        $fee_value = convertToNumber($fee_percentage_amount) + convertToNumber($fee_fixed_exchange);
    
                    } else if (!$fee_fixed && $fee_percentage > 0) {
                        
                        // Calculate fee value
                        $fee_value = convertToNumber($fee_percentage_amount);
    
                    } else if ($fee_fixed > 0 && !$fee_percentage) {
    
                        // Calculate fee value
                        $fee_value = convertToNumber($fee_fixed_exchange);
                        
                    } else if (!$fee_percentage && !$fee_fixed) {
                        
                        // Calculate fee value
                        $fee_value = 0;
    
                    }
                    
                    // Return fee value
                    return number_format($fee_value, 2, '.', '');
    
                break;

                // Gigs
                case 'gigs':

                    // Get gigs fixed fee
                    if (isset($this->settings->fixed_fee['gigs'])) {
                        
                        // Set fixed fee
                        $fee_fixed = convertToNumber($this->settings->fixed_fee['gigs']);
    
                    } else {
    
                        // No fixed fee
                        $fee_fixed = 0;
    
                    }
    
                    // Get gigs percentage fee
                    if (isset($this->settings->percentage_fee['gigs'])) {
                        
                        // Set percentage fee
                        $fee_percentage = convertToNumber($this->settings->percentage_fee['gigs']);
    
                    } else {
    
                        // No percentage fee
                        $fee_percentage = 0;
    
                    }
    
                    // Calculate percentage of this amount 
                    $fee_percentage_amount = $this->exchange( $fee_percentage * $amount / 100, $this->settings->exchange_rate );

                    // Calculate exchange rate of this fixed fee
                    $fee_fixed_exchange    = $this->exchange( $fee_fixed,  $this->settings->exchange_rate);
    
                    // Calculate fee value and visible text
                    if ($fee_fixed > 0 && $fee_percentage > 0) {
                        
                        // Calculate fee value
                        $fee_value = convertToNumber($fee_percentage_amount) + convertToNumber($fee_fixed_exchange);
    
                    } else if (!$fee_fixed && $fee_percentage > 0) {
                        
                        // Calculate fee value
                        $fee_value = convertToNumber($fee_percentage_amount);
    
                    } else if ($fee_fixed > 0 && !$fee_percentage) {
    
                        // Calculate fee value
                        $fee_value = convertToNumber($fee_fixed_exchange);
                        
                    } else if (!$fee_percentage && !$fee_fixed) {
                        
                        // Calculate fee value
                        $fee_value = 0;
    
                    }
    
                    // Return fee value
                    return $fee_value;

                break;
    
            }

        } catch (\Throwable $th) {
            
            // Something went wrong
            return 0;

        }
    }


    /**
     * Calculate exchange rate
     *
     * @param mixed $amount
     * @param mixed $exchange_rate
     * @param boolean $formatted
     * @param string $currency
     * @return mixed
     */
    private function exchange($amount, $exchange_rate, $formatted = false, $currency = null)
    {
        try {

            // Convert amount to number
            $amount                = convertToNumber($amount);

            // Get currency settings
            $currency_settings     = settings('currency');

            // Get default currency exchange rate
            $default_exchange_rate = convertToNumber($currency_settings->exchange_rate);

            // Get exchanged amount
            $exchanged_amount      = convertToNumber( $amount *  $default_exchange_rate / $exchange_rate );

            // Check if we have to return a formatted value
            if ($formatted) {
                
                return money( $exchanged_amount, $currency, true )->format();

            }

            // Return max deposit
            return convertToNumber(number_format( $exchanged_amount, 2, '.', '' ));

        } catch (\Throwable $th) {

            // Something went wrong
            return $amount;

        }
    }


    /**
     * Send a notification to user
     *
     * @param string $type
     * @param object $user
     * @return void
     */
    private function notification($type, $user)
    {
        try {
            
            // Check notification type
            switch ($type) {

                // Deposit funds
                case 'deposit':
                    


                break;

                // Gig checkout
                case 'gig':
                    
                    

                break;

                // Project payment
                case 'project':
                    
                    

                break;

                // Bid payment
                case 'bid':
                    
                    

                break;

            }

        } catch (\Throwable $th) {
            
            // Something went wrong
            return;

        }
    }


    /**
     * Redirecting
     *
     * @param string $type
     * @param string $status
     * @return void
     */
    private function redirect($type, $status = 'success')
    {
        // Check where to redirect
        switch ($type) {

            // Deposit history
            case 'deposit':
                
                // Check if payment succeeded
                if ($status === 'success') {
                    
                    // Redirect to deposit history page
                    return redirect('account/deposit/history')->with('success', __('messages.t_ur_transaction_has_completed'));

                } else if ($status === 'pending') {
                    
                    // Redirect to deposit history page
                    return redirect('account/deposit/history')->with('success', __('messages.t_mollie_payment_pending'));

                }
                

            break;

            // Gigs order
            case 'gigs':
                
                // Check if payment succeeded
                if ($status === 'success') {
                    
                    // Redirect to deposit history page
                    return redirect('account/orders')->with('success', __('messages.t_submit_ur_info_now_seller_start_order'));

                } else if ($status === 'pending') {
                    
                    // Redirect to deposit history page
                    return redirect('account/orders')->with('success', __('messages.t_mollie_payment_pending'));

                }

            break;

        }
    }
}
<?php
namespace App\Http\Controllers\Callback;

use App\Models\Gig;
use App\Models\User;
use App\Models\Order;
use App\Models\OrderItem;
use App\Models\GigUpgrade;
use Illuminate\Support\Str;
use App\Models\OrderInvoice;
use Illuminate\Http\Request;
use App\Models\DepositWebhook;
use App\Models\CheckoutWebhook;
use App\Models\OrderItemUpgrade;
use App\Models\DepositTransaction;
use App\Http\Controllers\Controller;
use App\Models\AffiliateTransaction;
use App\Models\AffiliateRegisteration;
use App\Models\AutomaticPaymentGateway;
use App\Notifications\User\Buyer\OrderPlaced;
use App\Notifications\User\Seller\PendingOrder;
use Srmklive\PayPal\Services\PayPal as PayPalClient;

class PaypalController extends Controller
{
    public $gateway = "paypal";
    public $status  = "paid";
    public $settings;


    /**
     * Payment gateway callback
     *
     * @param Request $request
     * @return mixed
     */
    public function callback(Request $request)
    {
        try {
            
            // Get payment gateway settings
            $settings       = AutomaticPaymentGateway::where('slug', $this->gateway)
                                                     ->where('is_active', true)
                                                     ->firstOrFail();

            // Set settings
            $this->settings = $settings;

            // Get transaction id
            $transaction_id = $request->get('order');

            // Check webhook event
            if ( $transaction_id ) {

                // Check if payment succeeded
                $response = $this->verify($transaction_id);
                
                // Check if payment succeeded
                if ( is_array($response) && $response['success'] === TRUE) {
                    
                    // Get order id
                    $order_id = $response['response']['purchase_units'][0]['payments']['captures'][0]['invoice_id'];

                    // Check if deposit callback
                    if (Str::startsWith($order_id, "D-")) {
                        
                        // Get saved webhook data in our database
                        $data = DepositWebhook::where('payment_id', $order_id)
                                                ->where('payment_method', $this->gateway)
                                                ->where('status', 'pending')
                                                ->firstOrFail();
        
                        // Handle deposit callback
                        $this->deposit($data->user_id, $data->amount, $order_id);

                        // Delete saved webhook data in our database
                        $data->delete();

                        // Redirecting
                        return $this->redirect('deposit');

                    }
    
                    // Check if checkout callback
                    if (Str::startsWith($order_id, "G-")) {
                        
                        // Get saved webhook data in our database
                        $data = CheckoutWebhook::where('payment_id', $order_id)
                                                ->where('payment_method', $this->gateway)
                                                ->where('status', 'pending')
                                                ->firstOrFail();
    
                        // Get cart
                        $cart = $data->data['cart'];
    
                        // Get user
                        $user = User::where('id', $data->data['buyer_id'])->firstOrFail();
        
                        // Handle deposit callback
                        $this->checkout($cart, $user, $order_id);

                        // Delete saved webhook data in our database
                        $data->delete();

                        // Redirecting
                        return $this->redirect('gigs');
    
                    }

                }

            }

            // In case failed redirect to home page
            return redirect('/');

        } catch (\Throwable $th) {

            // Error
            throw $th;

        }
    }


    /**
     * Verify if payment succeeded
     *
     * @param string $id
     * @return array
     */
    private function verify($id)
    {
        
            // Get payment gateway keys
            $client_id     = $this->settings?->settings['client_id'];
            $client_secret = $this->settings?->settings['client_secret'];
            $env           = $this->settings?->settings['env'];

            // Set gateway config
            $config = [
                'mode' => 'sandbox' ,
                'live' => [
                    'client_id'     => $client_id,
                    'client_secret' => $client_secret,
                    'app_id'        => '',
                ],
                'sandbox' => [
                    'client_id'     => $client_id,
                    'client_secret' => $client_secret,
                    'app_id'        => '',
                ],
                'payment_action' => 'Sale',
                'currency'       => $this->settings?->currency,
                'notify_url'     => 'https://2lancer.ma/paypal/notify',
                'locale'         => 'en_US',
                'validate_ssl'   => true,
            ];

            // Set paypal provider and config
            $client = new PayPalClient();
    
            // Set client credentials
            $client->setApiCredentials($config);

            // Get paypal access token
            $client->getAccessToken();

            // Capture this order
            $order  = $client->capturePaymentOrder($id);

            // Check if payment succeeded
            if ( is_array($order) && isset($order['status']) && $order['status'] === 'COMPLETED' ) {
                
                // Done
                return [
                    'success'  => true,
                    'response' => $order
                ];

            } else {

                // Failed
                return [
                    'success' => false,
                    'message' => __('messages.t_error_stripe_payment_failed')
                ];

            }

       
    }


    /**
     * Deposit funds into user's account
     *
     * @param int $user_id
     * @param mixed $amount
     * @param string $payment_id
     * @return void
     */
    private function deposit($user_id, $amount, $payment_id)
    {
        try {
            
            // Set amount
            $amount                  = convertToNumber($amount);
            
            // Calculate fee from this amount
            $fee                     = convertToNumber($this->fee('deposit', $amount)); 

            // Make transaction
            $deposit                 = new DepositTransaction();
            $deposit->user_id        = $user_id;
            $deposit->transaction_id = $payment_id;
            $deposit->payment_method = $this->gateway;
            $deposit->amount_total   = $amount;
            $deposit->amount_fee     = $fee;
            $deposit->amount_net     = $amount - $fee;
            $deposit->currency       = $this->settings->currency;
            $deposit->exchange_rate  = $this->settings->exchange_rate;
            $deposit->status         = $this->status;
            $deposit->ip_address     = request()->ip();
            $deposit->save();

            // Get user
            $user                    = User::where('id', $user_id)->firstOrFail();

            // Add funds
            $user->balance_available = convertToNumber($user->balance_available) + convertToNumber($deposit->amount_net);
            $user->save();

            // Send  a notification
            $this->notification('deposit', $user);

        } catch (\Throwable $th) {

            // Error
            throw $th;

        }
    }


    /**
     * Checkout
     *
     * @param array $cart
     * @param object $user
     * @param string $payment_id
     * @return void
     */
    private function checkout($cart, $user, $payment_id)
    {
        try {

            // Set empty variables
            $subtotal = 0;
            $total    = 0;
            $tax      = 0;
            $fee      = 0;

            // Loop through items in cart
            foreach ($cart as $key => $item) {
                    
                // Add gig price to subtotal
                $subtotal += convertToNumber($item['gig']['price']) * convertToNumber($item['quantity']);

                // Check if item has upgrades
                $upgrades  = $item['upgrades'];

                // Loop through upgrades
                if ( isset($upgrades) && is_array($upgrades) && count($upgrades) ) {
                    
                    // Loop through upgrades
                    foreach ($upgrades as $j => $upgrade) {
                        
                        // Check if upgrade checked
                        if ( isset($upgrade['checked']) && $upgrade['checked'] == 1 ) {
                            
                            // Add upgrade price to subtotal
                            $subtotal += convertToNumber($upgrade['price']) * convertToNumber($item['quantity']);

                        }

                    }

                }

            }

            // Get commission settings
            $commission_settings = settings('commission');

            // Check if taxes enabled
            if ($commission_settings->enable_taxes) {
                
                // Check if type of taxes percentage
                if ($commission_settings->tax_type === 'percentage') {
                    
                    // Set tax amount
                    $tax       = convertToNumber(bcmul($subtotal, $commission_settings->tax_value) / 100);

                } else {
                    
                    // Set tax amount
                    $tax       = convertToNumber($commission_settings->tax_value);

                }

            }

            // Calculate payment gateway fee
            $fee                   = convertToNumber($this->fee( 'gigs', $subtotal ));
            
            // Calculate total price
            $total                 = $subtotal + $tax + $fee;
        
            // Get user billing address
            $billing_info          = $user->billing;

            // Set unique id for this order
            $uid                   = uid();

            // Get buyer id
            $buyer_id              = $user->id;

            // Save order
            $order                 = new Order();
            $order->uid            = $uid;
            $order->buyer_id       = $buyer_id;
            $order->total_value    = $total;
            $order->subtotal_value = $subtotal;
            $order->taxes_value    = $tax;
            $order->save();

            // Loop through items in cart
            foreach ($cart as $key => $item) {
                    
                // Get gig
                $gig = Gig::where('uid', $item['id'])->with('owner')->active()->first();

                // Check if gig exists
                if ($gig) {
                    
                    // Set quantity
                    $quantity        = isset($item['quantity']) ? convertToNumber($item['quantity']) : 1;

                    // Set gig upgrades
                    $upgrades        = isset($item['upgrades']) && is_array($item['upgrades']) && count($item['upgrades']) ? $item['upgrades'] : [];

                    // Set empty variable
                    $upgrades_amount = 0;

                    // Loop through upgrades
                    foreach ($upgrades as $index => $upgrade) {
                        
                        // Check if upgrade is selected
                        if ( isset($upgrade['checked']) && $upgrade['checked'] == 1 ) {
                            
                            $upgrades_amount += convertToNumber($upgrade['price']) * $quantity;

                        }

                    }

                    // Set item total price
                    $item_total = $upgrades_amount + ( convertToNumber($item['gig']['price']) * $quantity );

                    // Calculate commission first
                    if ($commission_settings->commission_from === 'orders') {
                        
                        // Check commission type
                        if ($commission_settings->commission_type === 'percentage') {
                            
                            // Calculate commission
                            $commission = convertToNumber($commission_settings->commission_value) * $item_total / 100;
    
                        } else {
    
                            // Fixed amount
                            $commission = convertToNumber($commission_settings->commission_value);
    
                        }

                    } else {
                        
                        // No commission
                        $commission = 0;

                    }

                    // Save order item
                    $order_item                         = new OrderItem();
                    $order_item->uid                    = uid();
                    $order_item->order_id               = $order->id;
                    $order_item->gig_id                 = $gig->id;
                    $order_item->owner_id               = $gig->user_id;
                    $order_item->quantity               = $quantity;
                    $order_item->has_upgrades           = count($upgrades) ? true : false;
                    $order_item->total_value            = $item_total;
                    $order_item->profit_value           = $item_total - $commission;
                    $order_item->commission_value       = $commission;
                    $order_item->save();

                    // Loop through upgrades again
                    foreach ($upgrades as $index => $value) {
                        
                        // Check if upgrade is selected
                        if ( isset($upgrade['checked']) && $upgrade['checked'] == 1 ) {
                        
                            // Get upgrade
                            $upgrade = GigUpgrade::where('uid', $value['id'])->where('gig_id', $gig->id)->first();
    
                            // Check if upgrade exists
                            if ($upgrade) {
                                
                                // Save item upgrade
                                $order_item_upgrade             = new OrderItemUpgrade();
                                $order_item_upgrade->item_id    = $order_item->id;
                                $order_item_upgrade->title      = $upgrade->title;
                                $order_item_upgrade->price      = $upgrade->price;
                                $order_item_upgrade->extra_days = $upgrade->extra_days;
                                $order_item_upgrade->save();
    
                            }

                        }
                        
                    }

                    // Update seller pending balance
                    $gig->owner()->update([
                        'balance_pending' => convertToNumber($gig->owner->balance_pending) + convertToNumber($order_item->profit_value)
                    ]);

                    // Increment orders in queue
                    $gig->increment('orders_in_queue');

                    // Order item placed successfully
                    // Let's notify the seller about new order
                    $gig->owner->notify( (new PendingOrder($order_item))->locale(config('app.locale')) );

                    // Check user's level
                    check_user_level($buyer_id);

                    // Send notification
                    notification([
                        'text'    => 't_u_received_new_order_seller',
                        'action'  => url('seller/orders/details', $order_item->uid),
                        'user_id' => $order_item->owner_id
                    ]);

                }

            }

            // Save invoice
            $invoice                 = new OrderInvoice();
            $invoice->order_id       = $order->id;
            $invoice->payment_method = $this->gateway;
            $invoice->payment_id     = $payment_id;
            $invoice->firstname      = $billing_info->firstname ?? $user->username;
            $invoice->lastname       = $billing_info->lastname ?? $user->username;
            $invoice->email          = $user->email;
            $invoice->company        = !empty($billing_info->company) ? clean($billing_info->company) : null;
            $invoice->address        = !empty($billing_info->address) ? clean($billing_info->address) : "NA";
            $invoice->status         = 'paid';
            $invoice->save();

            // Update balance
            $user->update([
                'balance_purchases' => convertToNumber($user->balance_purchases) + convertToNumber($total)
            ]);

            // Now everything succeeded
            // Let's empty the cart
            session()->forget('cart');

            // Now let's notify the buyer that his order has been placed
            $user->notify( (new OrderPlaced($order, $total))->locale(config('app.locale')) );

            //check for affiliate registeration and check if expired 
            if(settings('affiliate')->is_enabled)
            {
            $affiliate_register =AffiliateRegisteration::where('user_id', $buyer_id)
                                                        ->where('expires_at','>',now())
                                                        ->first() ;
            if($affiliate_register){
                
                // get referral user
                $referral_user = User::where('id', $affiliate_register->referral_id)->first();
                
                // calculate referral earning
                $referral_earning =(convertToNumber(settings('affiliate')->profit_percentage)/100)*convertToNumber($total);
                   
                // add credit to referral wallet
                $referral_balance = convertToNumber($referral_user->balance_available) + $referral_earning;
                $referral_user->update(['balance_available'=>$referral_balance]);

                // create new affiliate transaction
                $affiliate_transaction = new AffiliateTransaction();
                $affiliate_transaction->user_id = $buyer_id ;
                $affiliate_transaction->referral_id = $referral_user->id ;
                $affiliate_transaction->order_id = $order->id ;
                $affiliate_transaction->referral_earning = $referral_earning ;
                $affiliate_transaction->save();
            }
            }


        } catch (\Throwable $th) {
            
            // Error
            throw $th;

        }
    }


    /**
     * Calculate fee value
     *
     * @param string $type
     * @param mixed $amount
     * @return mixed
     */
    private function fee($type, $amount = null)
    {
        try {
            
            // Set amount for deposit
            $amount = convertToNumber($amount) * $this->settings?->exchange_rate / settings('currency')->exchange_rate;

            // Remove long decimal
            $amount = convertToNumber( number_format($amount, 2, '.', '') );

            // Check fee type
            switch ($type) {
    
                // Deposit
                case 'deposit':
    
                    // Get deposit fixed fee
                    if (isset($this->settings->fixed_fee['deposit'])) {
                        
                        // Set fixed fee
                        $fee_fixed = convertToNumber($this->settings->fixed_fee['deposit']);
    
                    } else {
    
                        // No fixed fee
                        $fee_fixed = 0;
    
                    }
    
                    // Get deposit percentage fee
                    if (isset($this->settings->percentage_fee['deposit'])) {
                        
                        // Set percentage fee
                        $fee_percentage = convertToNumber($this->settings->percentage_fee['deposit']);
    
                    } else {
    
                        // No percentage fee
                        $fee_percentage = 0;
    
                    }
    
                    // Calculate percentage of this amount 
                    $fee_percentage_amount = $this->exchange( $fee_percentage * $amount / 100, $this->settings->exchange_rate );

                    // Calculate exchange rate of this fixed fee
                    $fee_fixed_exchange    = $this->exchange( $fee_fixed,  $this->settings->exchange_rate);
                    
                    // Calculate fee value and visible text
                    if ($fee_fixed > 0 && $fee_percentage > 0) {
                        
                        // Calculate fee value
                        $fee_value = convertToNumber($fee_percentage_amount) + convertToNumber($fee_fixed_exchange);
    
                    } else if (!$fee_fixed && $fee_percentage > 0) {
                        
                        // Calculate fee value
                        $fee_value = convertToNumber($fee_percentage_amount);
    
                    } else if ($fee_fixed > 0 && !$fee_percentage) {
    
                        // Calculate fee value
                        $fee_value = convertToNumber($fee_fixed_exchange);
                        
                    } else if (!$fee_percentage && !$fee_fixed) {
                        
                        // Calculate fee value
                        $fee_value = 0;
    
                    }
                    
                    // Return fee value
                    return number_format($fee_value, 2, '.', '');
    
                break;

                // Gigs
                case 'gigs':

                    // Get gigs fixed fee
                    if (isset($this->settings->fixed_fee['gigs'])) {
                        
                        // Set fixed fee
                        $fee_fixed = convertToNumber($this->settings->fixed_fee['gigs']);
    
                    } else {
    
                        // No fixed fee
                        $fee_fixed = 0;
    
                    }
    
                    // Get gigs percentage fee
                    if (isset($this->settings->percentage_fee['gigs'])) {
                        
                        // Set percentage fee
                        $fee_percentage = convertToNumber($this->settings->percentage_fee['gigs']);
    
                    } else {
    
                        // No percentage fee
                        $fee_percentage = 0;
    
                    }
    
                    // Calculate percentage of this amount 
                    $fee_percentage_amount = $this->exchange( $fee_percentage * $amount / 100, $this->settings->exchange_rate );

                    // Calculate exchange rate of this fixed fee
                    $fee_fixed_exchange    = $this->exchange( $fee_fixed,  $this->settings->exchange_rate);
    
                    // Calculate fee value and visible text
                    if ($fee_fixed > 0 && $fee_percentage > 0) {
                        
                        // Calculate fee value
                        $fee_value = convertToNumber($fee_percentage_amount) + convertToNumber($fee_fixed_exchange);
    
                    } else if (!$fee_fixed && $fee_percentage > 0) {
                        
                        // Calculate fee value
                        $fee_value = convertToNumber($fee_percentage_amount);
    
                    } else if ($fee_fixed > 0 && !$fee_percentage) {
    
                        // Calculate fee value
                        $fee_value = convertToNumber($fee_fixed_exchange);
                        
                    } else if (!$fee_percentage && !$fee_fixed) {
                        
                        // Calculate fee value
                        $fee_value = 0;
    
                    }
    
                    // Return fee value
                    return $fee_value;

                break;
    
            }

        } catch (\Throwable $th) {
            
            // Something went wrong
            return 0;

        }
    }


    /**
     * Calculate exchange rate
     *
     * @param mixed $amount
     * @param mixed $exchange_rate
     * @param boolean $formatted
     * @param string $currency
     * @return mixed
     */
    private function exchange($amount, $exchange_rate, $formatted = false, $currency = null)
    {
        try {

            // Convert amount to number
            $amount                = convertToNumber($amount);

            // Get currency settings
            $currency_settings     = settings('currency');

            // Get default currency exchange rate
            $default_exchange_rate = convertToNumber($currency_settings->exchange_rate);

            // Get exchanged amount
            $exchanged_amount      = convertToNumber( $amount *  $default_exchange_rate / $exchange_rate );

            // Check if we have to return a formatted value
            if ($formatted) {
                
                return money( $exchanged_amount, $currency, true )->format();

            }

            // Return max deposit
            return convertToNumber(number_format( $exchanged_amount, 2, '.', '' ));

        } catch (\Throwable $th) {

            // Something went wrong
            return $amount;

        }
    }


    /**
     * Send a notification to user
     *
     * @param string $type
     * @param object $user
     * @return void
     */
    private function notification($type, $user)
    {
        try {
            
            // Check notification type
            switch ($type) {

                // Deposit funds
                case 'deposit':
                    


                break;

                // Gig checkout
                case 'gig':
                    
                    

                break;

                // Project payment
                case 'project':
                    
                    

                break;

                // Bid payment
                case 'bid':
                    
                    

                break;

            }

        } catch (\Throwable $th) {
            
            // Something went wrong
            return;

        }
    }


    /**
     * Redirecting
     *
     * @param string $type
     * @param string $status
     * @return void
     */
    private function redirect($type, $status = 'success')
    {
        // Check where to redirect
        switch ($type) {

            // Deposit history
            case 'deposit':
                
                // Check if payment succeeded
                if ($status === 'success') {
                    
                    // Redirect to deposit history page
                    return redirect('account/deposit/history')->with('success', __('messages.t_ur_transaction_has_completed'));

                } else if ($status === 'pending') {
                    
                    // Redirect to deposit history page
                    return redirect('account/deposit/history')->with('success', __('messages.t_mollie_payment_pending'));

                }
                

            break;

            // Gigs order
            case 'gigs':
                
                // Check if payment succeeded
                if ($status === 'success') {
                    
                    // Redirect to deposit history page
                    return redirect('account/orders')->with('success', __('messages.t_submit_ur_info_now_seller_start_order'));

                } else if ($status === 'pending') {
                    
                    // Redirect to deposit history page
                    return redirect('account/orders')->with('success', __('messages.t_mollie_payment_pending'));

                }

            break;

        }
    }
}
<!DOCTYPE html>
<html>

<head>
    <style id="grid1">
        * {
          box-sizing: border-box;
        }
        .wrapper {
          max-width: 940px;
          margin: 0 auto;
        }
        
        .wrapper > div {
          border: 2px solid rgb(233 171 88);
          border-radius: 5px;
          background-color: rgb(233 171 88 / 50%);
          padding: 1em;
          color: #d9480f;
        }
        
        .wrapper {
          display: grid;
          grid-template-columns: repeat(3, 5fr);
          gap: 10px;
          grid-auto-rows: minmax(100px, auto);
        }
        .one {
          grid-column: 1 / 3;
          grid-row: 1;
        }
        .two {
          grid-column: 3 ;
          grid-row: 1 / 4;
        }
        .three {
          grid-column: 1;
          grid-row: 2 / 5;
        }
        .four {
          grid-column: 2;
          grid-row: 2 / 4;
        }
        .five {
          grid-column: 2;
          grid-row: 4;
        }
        .six {
          grid-column: 3;
          grid-row: 4;
        }
    </style>
    <style id="grid2">
    .item1 { grid-area: header; }
    .item2 { grid-area: menu; }
    .item3 { grid-area: main; }
    .item4 { grid-area: right; }
    .item5 { grid-area: footer; }

    .grid-container {
      display: grid;
      grid-template-areas:
        'header header header header header header'
        'menu main main main right right'
        'menu footer footer footer footer footer';
      gap: 10px;
      background-color: #2196F3;
      padding: 10px;
    }

    .grid-container > div {
      background-color: rgba(255, 255, 255, 0.8);
      text-align: center;
      padding: 20px 0;
      font-size: 30px;
    }
    </style>
</head>

<body>
    <div class="wrapper" id="grid1">
        <div class="one">One</div>
        <div class="two">Two</div>
        <div class="three">Three</div>
        <div class="four">Four</div>
        <div class="five">Five</div>
        <div class="six">Six</div>
    </div>
    <div class="grid-container" id="grid2">
        <div class="item1">Header</div>
        <div class="item2">Menu</div>
        <div class="item3">Main</div>  
        <div class="item4">Right</div>
        <div class="item5">Footer</div>
	</div>

</body>

</html>
i am learning javascript, i created a program to add two number using function
{
  "orgName": "Demo company",
  "edition": "Developer",
  "features": []
}
{
  "orgName": "Demo company",
  "edition": "Developer",
  "features": []
}
// Check to see if running in a Console
    var workspaceAPI = component.find("workspace");
    workspaceAPI.isConsoleNavigation().then(function(consoleResponse) {            
        console.log("IsConsole: ", consoleResponse);
        if (consoleResponse) {

            // Save current tab info
            workspaceAPI.getFocusedTabInfo().then(function(tabResponse) {
                var closeTabId = tabResponse.tabId;
                var closeTitle = tabResponse.title;
                var parentTabId = tabResponse.parentTabId;
                var isSubtab = tabResponse.isSubtab;
                console.log("Current Tab: ", closeTabId + " | " + closeTitle);
                console.log("Is Sub: ",isSubtab," ParentId: ",parentTabId);

                // Open Visualforce Page in a new tab
                if (isSubtab) {
                    workspaceAPI.openSubtab({
                        parentTabId: parentTabId,
                        url: vfURL,
                        focus: true
                    }).then(function(openSubResponse) {
                        console.log("New SubTab Id: ", openSubResponse);
                    })
                    .catch(function(error) {
                        console.log(error);
                    });                        
                } else {
                    workspaceAPI.openTab({
                        url: vfURL,
                        focus: true
                    }).then(function(openParResponse) {
                        console.log("New ParentTab Id: ", openParResponse);
                    })
                    .catch(function(error) {
                        console.log(error);
                    });                        
                }

                // Because exiting the VF page will reopen the object record,
                // close the tab we started on
                if (tabResponse.closeable && !tabResponse.pinned) {
                    workspaceAPI.closeTab({
                        tabId: closeTabId
                    }).then(function(closeResponse) {
                        console.log("Closed: ", closeTitle);                      
                    })
                    .catch(function(error) {
                        console.log(error);
                    });                            
                } else {
                    console.log("Left Open: ", tabResponse.title);
                }
            })
            .catch(function(error) {
                console.log(error);
            })
                // Handle non-console user
                console.log("Not in Console");
                var urlEvent = $A.get("e.force:navigateToURL");
                urlEvent.setParams({
                     "url": vfURL
                });
                urlEvent.fire();
    doInit : function(component, event, helper) {
        var params = new Array();
        params.push(component.get('v.recordIdVar') + '=' + component.get('v.recordId'));
        params.push(component.get('v.otherParams'));
        component.set('v.queryString', params.join('&'))
    },

    openPage : function(component, event, helper) {

        // Show spinner once button is pressed
        var spinner = component.find('spinner');
        $A.util.removeClass(spinner, 'slds-hide');

        // Build url for Visualforce page
        var vfURL = 'https://' + component.get("v.domain") + '--c.visualforce.com/apex/';
        vfURL = vfURL + component.get("v.pageName") + '?';
        vfURL = vfURL + component.get("v.queryString");
        console.log("VF URL: ",vfURL);
<aura:component implements="flexipage:availableForAllPageTypes,force:hasRecordId" access="global">

    <lightning:workspaceAPI aura:id="workspace" />

    <aura:attribute name="buttonLabel" type="String" />
    <aura:attribute name="buttonVariant" type="String" default="neutral" />
    <aura:attribute name="domain" type="String" />
    <aura:attribute name="pageName" type="String" />
    <aura:attribute name="recordIdVar" type="String" />
    <aura:attribute name="otherParams" type="String" />

    <aura:attribute name="queryString" type="String" />

    <aura:handler name="init" value="{!this}" action="{!c.doInit}" />

    <lightning:card>
        <lightning:layoutItem padding="around-small">
            <lightning:button label="{!v.buttonLabel}" variant="{!v.buttonVariant}" onclick="{!c.openPage}" />
            <lightning:spinner aura:id="spinner" alternativeText="Loading" variant="brand" size="large" class="slds-hide" />
        </lightning:layoutItem>
    </lightning:card>

</aura:component>
star

Mon Aug 19 2024 13:47:23 GMT+0000 (Coordinated Universal Time) https://codepen.io/robertostringa/pen/zYVRWJZ

@rstringa

star

Mon Aug 19 2024 12:14:08 GMT+0000 (Coordinated Universal Time) https://maticz.com/multiplayer-game-development

@carolinemax #maticz #multiplayer_game_development

star

Mon Aug 19 2024 10:20:49 GMT+0000 (Coordinated Universal Time)

@manhmd #java

star

Mon Aug 19 2024 06:08:06 GMT+0000 (Coordinated Universal Time)

@hyzzzz #python

star

Mon Aug 19 2024 06:07:19 GMT+0000 (Coordinated Universal Time)

@WXAPAC

star

Mon Aug 19 2024 05:58:21 GMT+0000 (Coordinated Universal Time) https://htm-rapportage.eu.qlikcloud.com/dataloadeditor/app/9e01ce59-e241-41dc-aca1-5490cddba9c2/hubUrl//catalog

@bogeyboogaard

star

Sun Aug 18 2024 21:41:11 GMT+0000 (Coordinated Universal Time)

@FOHWellington

star

Sun Aug 18 2024 18:22:27 GMT+0000 (Coordinated Universal Time) https://www.youtube.com/watch?v

@Tomsims

star

Sun Aug 18 2024 16:57:03 GMT+0000 (Coordinated Universal Time)

@mayeul_rougevin

star

Sun Aug 18 2024 13:03:19 GMT+0000 (Coordinated Universal Time)

@hkrishn4a

star

Sun Aug 18 2024 10:43:59 GMT+0000 (Coordinated Universal Time) https://www.itn.liu.se/~aidvi05/cplusplus/my-docs/Vectors/basics.html

@ssjuniverse

star

Sun Aug 18 2024 09:50:12 GMT+0000 (Coordinated Universal Time) https://github.com/Matthew-J-Spencer/Ultimate-2D-Controller

@jakebezz

star

Sun Aug 18 2024 08:38:27 GMT+0000 (Coordinated Universal Time) https://www.learncbse.in/class-12-informatics-practices-notes-chapter-11/

@A97v1

star

Sun Aug 18 2024 06:59:01 GMT+0000 (Coordinated Universal Time) https://kipofashion.com/product-category/dresses/

@kipofashion #digitalprintdresses #digitalprintdressesorwomen

star

Sat Aug 17 2024 23:14:36 GMT+0000 (Coordinated Universal Time) https://wpsimplehacks.com/how-to-create-custom-tabs/

@mediasolutions

star

Sat Aug 17 2024 23:14:15 GMT+0000 (Coordinated Universal Time) https://wpsimplehacks.com/how-to-create-custom-tabs/

@mediasolutions

star

Sat Aug 17 2024 23:14:08 GMT+0000 (Coordinated Universal Time) https://wpsimplehacks.com/how-to-create-custom-tabs/

@mediasolutions

star

Sat Aug 17 2024 23:14:08 GMT+0000 (Coordinated Universal Time) https://wpsimplehacks.com/how-to-create-custom-tabs/

@mediasolutions

star

Sat Aug 17 2024 20:23:30 GMT+0000 (Coordinated Universal Time)

@iamkatmakhafola

star

Sat Aug 17 2024 18:55:42 GMT+0000 (Coordinated Universal Time) https://www.appsheet.com/template/AppDef?appName

@Wittinunt

star

Sat Aug 17 2024 17:44:37 GMT+0000 (Coordinated Universal Time) https://www.ntlite.com/community/index.php?threads/content-delivery-manager-vs-automatic-installation-of-sponsored-apps.4684/#post-45992

@Curable1600 #windows #ntlite

star

Sat Aug 17 2024 08:42:19 GMT+0000 (Coordinated Universal Time) https://github.com/marketplace/actions/run-ssh-command

@acassell

star

Sat Aug 17 2024 08:41:49 GMT+0000 (Coordinated Universal Time) https://github.com/marketplace/actions/fork-sync

@acassell

star

Sat Aug 17 2024 08:41:16 GMT+0000 (Coordinated Universal Time) https://github.com/marketplace/actions/labeler

@acassell

star

Sat Aug 17 2024 08:39:39 GMT+0000 (Coordinated Universal Time) https://github.com/marketplace/actions/setup-php-action

@acassell

star

Sat Aug 17 2024 08:12:59 GMT+0000 (Coordinated Universal Time) https://github.com/mriscoc/Ender3V2S1/discussions/1092

@amccall23

star

Sat Aug 17 2024 08:12:56 GMT+0000 (Coordinated Universal Time) https://github.com/mriscoc/Ender3V2S1/discussions/1092

@amccall23

star

Sat Aug 17 2024 08:11:54 GMT+0000 (Coordinated Universal Time) https://github.com/actions/setup-node

@acassell

star

Sat Aug 17 2024 08:05:53 GMT+0000 (Coordinated Universal Time) https://docs.github.com/en/actions/use-cases-and-examples/deploying/deploying-nodejs-to-azure-app-service

@acassell

star

Sat Aug 17 2024 08:04:57 GMT+0000 (Coordinated Universal Time) https://docs.github.com/en/actions/use-cases-and-examples/building-and-testing/building-and-testing-python

@acassell

star

Sat Aug 17 2024 02:53:19 GMT+0000 (Coordinated Universal Time) https://uiverse.io/andrew-demchenk0/stupid-emu-68

@SebasOfEek #css

star

Sat Aug 17 2024 02:52:50 GMT+0000 (Coordinated Universal Time) https://uiverse.io/andrew-demchenk0/bad-squid-34

@SebasOfEek #css

star

Sat Aug 17 2024 02:46:58 GMT+0000 (Coordinated Universal Time) https://uiverse.io/akshat-patel28/tough-octopus-19

@SebasOfEek #css

star

Sat Aug 17 2024 01:20:17 GMT+0000 (Coordinated Universal Time)

@mebean #flutter #laravel #api #http #2lancer

star

Sat Aug 17 2024 00:58:14 GMT+0000 (Coordinated Universal Time)

@mebean #flutter #laravel #api #http #2lancer

star

Sat Aug 17 2024 00:56:17 GMT+0000 (Coordinated Universal Time)

@mebean #flutter #laravel #api #http #2lancer

star

Sat Aug 17 2024 00:55:54 GMT+0000 (Coordinated Universal Time)

@mebean #flutter #laravel #api #http #2lancer

star

Sat Aug 17 2024 00:54:26 GMT+0000 (Coordinated Universal Time) https://2lancer.ma/page/terms

@mebean #flutter #laravel #api #http #2lancer

star

Fri Aug 16 2024 20:39:04 GMT+0000 (Coordinated Universal Time)

@ASPX #css #html

star

Fri Aug 16 2024 20:08:36 GMT+0000 (Coordinated Universal Time) https://onecompiler.com/javascript

@muneeb

star

Fri Aug 16 2024 17:39:40 GMT+0000 (Coordinated Universal Time) https://github.com/SalesforceFoundation

@shawnclevinger

star

Fri Aug 16 2024 17:39:05 GMT+0000 (Coordinated Universal Time) https://github.com/developerforce

@shawnclevinger

star

Fri Aug 16 2024 17:38:25 GMT+0000 (Coordinated Universal Time) https://github.com/SalesforceLabs

@shawnclevinger

star

Fri Aug 16 2024 16:54:01 GMT+0000 (Coordinated Universal Time) flow_action_components/DedupeRecordCollection/config/project-scratch-def.json

@shawnclevinger

star

Fri Aug 16 2024 16:52:01 GMT+0000 (Coordinated Universal Time) flow_action_components/DedupeRecordCollection/config/project-scratch-def.json

@shawnclevinger

star

Fri Aug 16 2024 15:50:01 GMT+0000 (Coordinated Universal Time) https://unofficialsf.com/load-a-visualforce-page-with-parameters-in-lightning/

@shawnclevinger

star

Fri Aug 16 2024 15:48:52 GMT+0000 (Coordinated Universal Time) https://unofficialsf.com/load-a-visualforce-page-with-parameters-in-lightning/

@shawnclevinger

star

Fri Aug 16 2024 15:48:19 GMT+0000 (Coordinated Universal Time) https://unofficialsf.com/load-a-visualforce-page-with-parameters-in-lightning/

@shawnclevinger

star

Fri Aug 16 2024 15:45:38 GMT+0000 (Coordinated Universal Time) https://unofficialsf.com/load-a-visualforce-page-with-parameters-in-lightning/

@shawnclevinger

Save snippets that work with our extensions

Available in the Chrome Web Store Get Firefox Add-on Get VS Code extension