This commit is contained in:
parent
8354634117
commit
39265bfcb1
BIN
docs/.DS_Store
vendored
Normal file
BIN
docs/.DS_Store
vendored
Normal file
Binary file not shown.
@ -136,20 +136,37 @@ const E=[
|
||||
{cat:"Master Data / Postal Code",m:"post",p:"/master-data/postal-codes/import",s:"Import postal codes from CSV",q:[],rb:"_MULTIPART_",rbe:"{\n \"success\": true,\n \"data\": {\n \"job_id\": \"job_abc123def456\",\n \"total_rows\": 100,\n \"imported\": 95,\n \"skipped\": 5,\n \"logs\": [\n {\n \"row\": 2,\n \"status\": \"skipped\",\n \"data\": \"Jawa Barat\",\n \"message\": \"duplicate\"\n }\n ],\n \"errors\": [],\n \"is_async\": false\n }\n}",rf:[]},
|
||||
{cat:"Master Data / Postal Code",m:"post",p:"/master-data/postal-codes/import/stop",s:"Stop postal code import job",q:[],rb:"{\n \"job_id\": \"job_abc123def456\"\n}",rbe:"{\n \"success\": true,\n \"message\": \"Job stopped\"\n}",rf:["job_id"]},
|
||||
{cat:"Master Data / Postal Code",m:"get",p:"/master-data/postal-codes/import/status/:jobId",s:"Check postal code import job status",q:[{n:"jobId",t:"string",req:true,d:"Async job ID"}],rb:null,rbe:"{\n \"success\": true,\n \"data\": {\n \"job\": {\n \"id\": \"job_abc123def456\",\n \"status\": \"completed\",\n \"total\": 100,\n \"imported\": 95,\n \"skipped\": 5\n },\n \"logs\": []\n }\n}",rf:[]},
|
||||
{cat:"Master Data / Cost Component",m:"get",p:"/master-data/cost-components/",s:"Get all cost components",q:[{n:"name",t:"string",req:false,d:"Filter by name"},{n:"code",t:"string",req:false,d:"Filter by code"},{n:"component_type",t:"integer",req:false,d:"Filter by type (0=Input, 1=Formula)"}],rb:null,rbe:"{\n \"success\": true,\n \"data\": [\n {\n \"id\": \"01HXYZ123456789012345678\",\n \"name\": \"Biaya Pengiriman\",\n \"code\": \"SHIP\",\n \"inc\": 1,\n \"value\": \"15000\",\n \"component_type\": 0,\n \"merchant_id\": \"01HXYZ123456789012345678\"\n }\n ]\n}",rf:[]},
|
||||
{cat:"Master Data / Cost Component",m:"get",p:"/master-data/cost-components/",s:"Get all cost components",q:[{n:"name",t:"string",req:false,d:"Filter by name"},{n:"code",t:"string",req:false,d:"Filter by code"},{n:"component_type",t:"integer",req:false,d:"Filter by type (0=Input, 1=Formula)"}],rb:null,rbe:"{\n \"success\": true,\n \"data\": [\n {\n \"id\": \"01HXYZ123456789012345678\",\n \"name\": \"Biaya Pengiriman\",\n \"code\": \"SHIP\",\n \"inc\": 1,\n \"value\": \"15000\",\n \"component_type\": 0,\n \"unit_type\": 0,\n \"merchant_id\": \"01HXYZ123456789012345678\"\n }\n ]\n}",rf:[]},
|
||||
{cat:"Master Data / Cost Component",m:"post",p:"/master-data/cost-components/list",s:"Cost component list (DataTable)",q:[],rb:"_DT_",rbe:"{\n \"success\": true,\n \"data\": {\n \"draw\": 1,\n \"recordsTotal\": 34,\n \"recordsFiltered\": 34,\n \"data\": [\n { \"id\": \"01HXYZ123456789012345678\", \"name\": \"...\" }\n ]\n }\n}",rf:[]},
|
||||
{cat:"Master Data / Cost Component",m:"get",p:"/master-data/cost-components/:id",s:"Get cost component by ID",q:[{n:"id",t:"string",req:true,d:"Cost component ID"}],rb:null,rbe:"{\n \"success\": true,\n \"data\": {\n \"id\": \"01HXYZ123456789012345678\",\n \"name\": \"Biaya Pengiriman\",\n \"code\": \"SHIP\",\n \"inc\": 1,\n \"value\": \"15000\",\n \"component_type\": 0,\n \"merchant_id\": \"01HXYZ123456789012345678\"\n }\n}",rf:[]},
|
||||
{cat:"Master Data / Cost Component",m:"post",p:"/master-data/cost-components/",s:"Create cost component",q:[],rb:"{\n \"name\": \"Biaya Pengiriman\",\n \"code\": \"SHIP\",\n \"value\": \"15000\",\n \"component_type\": 0\n}",rbe:"{\n \"success\": true,\n \"data\": {\n \"id\": \"01HXYZ123456789012345678\",\n \"name\": \"Biaya Pengiriman\",\n \"code\": \"SHIP\",\n \"inc\": 1,\n \"value\": \"15000\",\n \"component_type\": 0,\n \"merchant_id\": \"01HXYZ123456789012345678\"\n }\n}",rf:["name","code","value"]},
|
||||
{cat:"Master Data / Cost Component",m:"put",p:"/master-data/cost-components/:id",s:"Update cost component",q:[{n:"id",t:"string",req:true,d:"Cost component ID"}],rb:"{\n \"name\": \"Biaya Pengiriman Updated\",\n \"code\": \"SHIP\",\n \"value\": \"20000\",\n \"component_type\": 0\n}",rbe:"{\n \"success\": true,\n \"data\": {\n \"id\": \"01HXYZ123456789012345678\",\n \"name\": \"Biaya Pengiriman Updated\",\n \"code\": \"SHIP\",\n \"inc\": 1,\n \"value\": \"20000\",\n \"component_type\": 0,\n \"merchant_id\": \"01HXYZ123456789012345678\"\n }\n}",rf:["name","code","value"]},
|
||||
{cat:"Master Data / Cost Component",m:"get",p:"/master-data/cost-components/:id",s:"Get cost component by ID",q:[{n:"id",t:"string",req:true,d:"Cost component ID"}],rb:null,rbe:"{\n \"success\": true,\n \"data\": {\n \"id\": \"01HXYZ123456789012345678\",\n \"name\": \"Biaya Pengiriman\",\n \"code\": \"SHIP\",\n \"inc\": 1,\n \"value\": \"15000\",\n \"component_type\": 0,\n \"unit_type\": 0,\n \"merchant_id\": \"01HXYZ123456789012345678\"\n }\n}",rf:[]},
|
||||
{cat:"Master Data / Cost Component",m:"post",p:"/master-data/cost-components/",s:"Create cost component",q:[],rb:"{\n \"name\": \"Biaya Pengiriman\",\n \"code\": \"SHIP\",\n \"value\": \"15000\",\n \"component_type\": 0,\n \"unit_type\": 0\n}",rbe:"{\n \"success\": true,\n \"data\": {\n \"id\": \"01HXYZ123456789012345678\",\n \"name\": \"Biaya Pengiriman\",\n \"code\": \"SHIP\",\n \"inc\": 1,\n \"value\": \"15000\",\n \"component_type\": 0,\n \"unit_type\": 0,\n \"merchant_id\": \"01HXYZ123456789012345678\"\n }\n}",rf:["name","code","value"]},
|
||||
{cat:"Master Data / Cost Component",m:"put",p:"/master-data/cost-components/:id",s:"Update cost component",q:[{n:"id",t:"string",req:true,d:"Cost component ID"}],rb:"{\n \"name\": \"Biaya Pengiriman Updated\",\n \"code\": \"SHIP\",\n \"value\": \"20000\",\n \"component_type\": 0,\n \"unit_type\": 0\n}",rbe:"{\n \"success\": true,\n \"data\": {\n \"id\": \"01HXYZ123456789012345678\",\n \"name\": \"Biaya Pengiriman Updated\",\n \"code\": \"SHIP\",\n \"inc\": 1,\n \"value\": \"20000\",\n \"component_type\": 0,\n \"unit_type\": 0,\n \"merchant_id\": \"01HXYZ123456789012345678\"\n }\n}",rf:["name","code","value"]},
|
||||
{cat:"Master Data / Cost Component",m:"delete",p:"/master-data/cost-components/:id",s:"Delete cost component",q:[{n:"id",t:"string",req:true,d:"Cost component ID"}],rb:null,rbe:"{\n \"success\": true,\n \"message\": \"cost component deleted\"\n}",rf:[]},
|
||||
{cat:"Master Data / Cost Component",m:"post",p:"/master-data/cost-components/sortup",s:"Move cost component up in sort order",q:[],rb:"{\n \"id\": \"01HXYZ123456789012345678\"\n}",rbe:"{\n \"success\": true,\n \"message\": \"Sorting Up Success\"\n}",rf:["id"]},
|
||||
{cat:"Master Data / Cost Component",m:"post",p:"/master-data/cost-components/sortdown",s:"Move cost component down in sort order",q:[],rb:"{\n \"id\": \"01HXYZ123456789012345678\"\n}",rbe:"{\n \"success\": true,\n \"message\": \"Sorting Down Success\"\n}",rf:["id"]},
|
||||
{cat:"Basic Pricing",m:"get",p:"/basic-pricings/",s:"Get all basic pricings",q:[{n:"name",t:"string",req:false,d:"Filter by name"},{n:"province_source_id",t:"string",req:false,d:"Source province ID"},{n:"city_source_id",t:"string",req:false,d:"Source city ID"},{n:"package_type_id",t:"string",req:false,d:"Package type ID"},{n:"moda_id",t:"string",req:false,d:"Transport mode ID"}],rb:null,rbe:"{\\n \"success\": true,\\n \"data\": [\\n { ... }\\n ]\\n}",rf:[]},
|
||||
{cat:"Basic Pricing",m:"get",p:"/basic-pricings/",s:"Get all basic pricings",q:[{n:"province_source_id",t:"string",req:false,d:"Source province ID"},{n:"city_source_id",t:"string",req:false,d:"Source city ID"},{n:"package_type_id",t:"string",req:false,d:"Package type ID"},{n:"moda_id",t:"string",req:false,d:"Transport mode ID"}],rb:null,rbe:"{\\n \"success\": true,\\n \"data\": [\\n { ... }\\n ]\\n}",rf:[]},
|
||||
{cat:"Basic Pricing",m:"post",p:"/basic-pricings/list",s:"Basic pricing list (DataTable)",q:[],rb:"_DT_",rbe:"{\n \"success\": true,\n \"data\": {\n \"draw\": 1,\n \"recordsTotal\": 34,\n \"recordsFiltered\": 34,\n \"data\": [\n { \"id\": \"01HXYZ123456789012345678\", \"name\": \"...\" }\n ]\n }\n}",rf:[]},
|
||||
{cat:"Basic Pricing",m:"get",p:"/basic-pricings/:id",s:"Get basic pricing by ID",q:[{n:"id",t:"string",req:true,d:"Basic pricing ID"}],rb:null,rbe:"{\n \"success\": true,\n \"data\": {\n \"id\": \"01HXYZ123456789012345678\",\n \"name\": \"Basic Price Bandung-Jakarta\",\n \"province_source_id\": \"01HXYZ123456789012345678\",\n \"city_source_id\": \"01HXYZ123456789012345678\",\n \"district_source_id\": \"01HXYZ123456789012345678\",\n \"subdistrict_source_id\": \"01HXYZ123456789012345678\",\n \"postal_code_source_id\": \"01HXYZ123456789012345678\",\n \"province_destination_id\": \"01HXYZ123456789012345678\",\n \"city_destination_id\": \"01HXYZ123456789012345678\",\n \"district_destination_id\": \"01HXYZ123456789012345678\",\n \"subdistrict_destination_id\": \"01HXYZ123456789012345678\",\n \"postal_code_destination_id\": \"01HXYZ123456789012345678\",\n \"package_type_id\": \"01HXYZ123456789012345678\",\n \"moda_id\": \"01HXYZ123456789012345678\",\n \"merchant_id\": \"01HXYZ123456789012345678\",\n \"components\": [\n {\n \"id\": \"01HXYZ123456789012345678\",\n \"cost_component_id\": \"01HXYZ123456789012345678\",\n \"value\": 15000\n }\n ]\n }\n}",rf:[]},
|
||||
{cat:"Basic Pricing",m:"post",p:"/basic-pricings/",s:"Create basic pricing",q:[],rb:"{\n \"name\": \"Basic Price Bandung-Jakarta\",\n \"province_source_id\": \"01HXYZ123456789012345678\",\n \"city_source_id\": \"01HXYZ123456789012345678\",\n \"district_source_id\": \"01HXYZ123456789012345678\",\n \"subdistrict_source_id\": \"01HXYZ123456789012345678\",\n \"postal_code_source_id\": \"01HXYZ123456789012345678\",\n \"province_destination_id\": \"01HXYZ123456789012345678\",\n \"city_destination_id\": \"01HXYZ123456789012345678\",\n \"district_destination_id\": \"01HXYZ123456789012345678\",\n \"subdistrict_destination_id\": \"01HXYZ123456789012345678\",\n \"postal_code_destination_id\": \"01HXYZ123456789012345678\",\n \"package_type_id\": \"01HXYZ123456789012345678\",\n \"moda_id\": \"01HXYZ123456789012345678\",\n \"components\": [\n {\n \"cost_component_id\": \"01HXYZ123456789012345678\",\n \"value\": 15000\n }\n ]\n}",rbe:"{\n \"success\": true,\n \"data\": {\n \"id\": \"01HXYZ123456789012345678\",\n \"name\": \"Basic Price Bandung-Jakarta\",\n \"province_source_id\": \"01HXYZ123456789012345678\",\n \"city_source_id\": \"01HXYZ123456789012345678\",\n \"district_source_id\": \"01HXYZ123456789012345678\",\n \"subdistrict_source_id\": \"01HXYZ123456789012345678\",\n \"postal_code_source_id\": \"01HXYZ123456789012345678\",\n \"province_destination_id\": \"01HXYZ123456789012345678\",\n \"city_destination_id\": \"01HXYZ123456789012345678\",\n \"district_destination_id\": \"01HXYZ123456789012345678\",\n \"subdistrict_destination_id\": \"01HXYZ123456789012345678\",\n \"postal_code_destination_id\": \"01HXYZ123456789012345678\",\n \"package_type_id\": \"01HXYZ123456789012345678\",\n \"moda_id\": \"01HXYZ123456789012345678\",\n \"merchant_id\": \"01HXYZ123456789012345678\",\n \"components\": [\n {\n \"id\": \"01HXYZ123456789012345678\",\n \"cost_component_id\": \"01HXYZ123456789012345678\",\n \"value\": 15000\n }\n ]\n }\n}",rf:["name"]},
|
||||
{cat:"Basic Pricing",m:"put",p:"/basic-pricings/:id",s:"Update basic pricing",q:[{n:"id",t:"string",req:true,d:"Basic pricing ID"}],rb:"{\n \"name\": \"Basic Price Bandung-Jakarta\",\n \"province_source_id\": \"01HXYZ123456789012345678\",\n \"city_source_id\": \"01HXYZ123456789012345678\",\n \"district_source_id\": \"01HXYZ123456789012345678\",\n \"subdistrict_source_id\": \"01HXYZ123456789012345678\",\n \"postal_code_source_id\": \"01HXYZ123456789012345678\",\n \"province_destination_id\": \"01HXYZ123456789012345678\",\n \"city_destination_id\": \"01HXYZ123456789012345678\",\n \"district_destination_id\": \"01HXYZ123456789012345678\",\n \"subdistrict_destination_id\": \"01HXYZ123456789012345678\",\n \"postal_code_destination_id\": \"01HXYZ123456789012345678\",\n \"package_type_id\": \"01HXYZ123456789012345678\",\n \"moda_id\": \"01HXYZ123456789012345678\",\n \"components\": [\n {\n \"cost_component_id\": \"01HXYZ123456789012345678\",\n \"value\": 15000\n }\n ]\n}",rbe:"{\n \"success\": true,\n \"data\": {\n \"id\": \"01HXYZ123456789012345678\",\n \"name\": \"Basic Price Bandung-Jakarta\",\n \"province_source_id\": \"01HXYZ123456789012345678\",\n \"city_source_id\": \"01HXYZ123456789012345678\",\n \"district_source_id\": \"01HXYZ123456789012345678\",\n \"subdistrict_source_id\": \"01HXYZ123456789012345678\",\n \"postal_code_source_id\": \"01HXYZ123456789012345678\",\n \"province_destination_id\": \"01HXYZ123456789012345678\",\n \"city_destination_id\": \"01HXYZ123456789012345678\",\n \"district_destination_id\": \"01HXYZ123456789012345678\",\n \"subdistrict_destination_id\": \"01HXYZ123456789012345678\",\n \"postal_code_destination_id\": \"01HXYZ123456789012345678\",\n \"package_type_id\": \"01HXYZ123456789012345678\",\n \"moda_id\": \"01HXYZ123456789012345678\",\n \"merchant_id\": \"01HXYZ123456789012345678\",\n \"components\": [\n {\n \"id\": \"01HXYZ123456789012345678\",\n \"cost_component_id\": \"01HXYZ123456789012345678\",\n \"value\": 15000\n }\n ]\n }\n}",rf:["name"]},
|
||||
{cat:"Basic Pricing",m:"delete",p:"/basic-pricings/:id",s:"Delete basic pricing",q:[{n:"id",t:"string",req:true,d:"Basic pricing ID"}],rb:null,rbe:"{\n \"success\": true,\n \"message\": \"basic pricing deleted\"\n}",rf:[]}
|
||||
{cat:"Basic Pricing",m:"get",p:"/basic-pricings/:id",s:"Get basic pricing by ID",q:[{n:"id",t:"string",req:true,d:"Basic pricing ID"}],rb:null,rbe:"{\n \"success\": true,\n \"data\": {\n \"id\": \"01HXYZ123456789012345678\",\n \"province_source_id\": \"01HXYZ123456789012345678\",\n \"city_source_id\": \"01HXYZ123456789012345678\",\n \"district_source_id\": \"01HXYZ123456789012345678\",\n \"subdistrict_source_id\": \"01HXYZ123456789012345678\",\n \"postal_code_source_id\": \"01HXYZ123456789012345678\",\n \"province_destination_id\": \"01HXYZ123456789012345678\",\n \"city_destination_id\": \"01HXYZ123456789012345678\",\n \"district_destination_id\": \"01HXYZ123456789012345678\",\n \"subdistrict_destination_id\": \"01HXYZ123456789012345678\",\n \"postal_code_destination_id\": \"01HXYZ123456789012345678\",\n \"package_type_id\": \"01HXYZ123456789012345678\",\n \"moda_id\": \"01HXYZ123456789012345678\",\n \"lead_time\": \"2-3 days\",\n \"minimum_weight\": 1.0,\n \"merchant_id\": \"01HXYZ123456789012345678\",\n \"components\": [\n {\n \"id\": \"01HXYZ123456789012345678\",\n \"cost_component_id\": \"01HXYZ123456789012345678\",\n \"value\": \"15000\"\n }\n ]\n }\n}",rf:[]},
|
||||
{cat:"Basic Pricing",m:"post",p:"/basic-pricings/match",s:"Match basic pricing by ID",q:[],rb:"{\n \"id\": \"01HXYZ123456789012345678\"\n}",rbe:"{\n \"success\": true,\n \"data\": {\n \"id\": \"01HXYZ123456789012345678\",\n \"components\": [\n {\n \"id\": \"01HXYZ123456789012345678\",\n \"cost_component_id\": \"01HXYZ123456789012345678\",\n \"value\": \"15000\"\n }\n ]\n }\n}",rf:["id"]},
|
||||
{cat:"Basic Pricing",m:"post",p:"/basic-pricings/",s:"Create basic pricing",q:[],rb:"{\n \"province_source_id\": \"01HXYZ123456789012345678\",\n \"city_source_id\": \"01HXYZ123456789012345678\",\n \"district_source_id\": \"01HXYZ123456789012345678\",\n \"subdistrict_source_id\": \"01HXYZ123456789012345678\",\n \"postal_code_source_id\": \"01HXYZ123456789012345678\",\n \"province_destination_id\": \"01HXYZ123456789012345678\",\n \"city_destination_id\": \"01HXYZ123456789012345678\",\n \"district_destination_id\": \"01HXYZ123456789012345678\",\n \"subdistrict_destination_id\": \"01HXYZ123456789012345678\",\n \"postal_code_destination_id\": \"01HXYZ123456789012345678\",\n \"package_type_id\": \"01HXYZ123456789012345678\",\n \"moda_id\": \"01HXYZ123456789012345678\",\n \"lead_time\": \"2-3 days\",\n \"minimum_weight\": 1.0,\n \"components\": [\n {\n \"cost_component_id\": \"01HXYZ123456789012345678\",\n \"value\": \"15000\"\n }\n ]\n}",rbe:"{\n \"success\": true,\n \"data\": {\n \"id\": \"01HXYZ123456789012345678\",\n \"province_source_id\": \"01HXYZ123456789012345678\",\n \"city_source_id\": \"01HXYZ123456789012345678\",\n \"district_source_id\": \"01HXYZ123456789012345678\",\n \"subdistrict_source_id\": \"01HXYZ123456789012345678\",\n \"postal_code_source_id\": \"01HXYZ123456789012345678\",\n \"province_destination_id\": \"01HXYZ123456789012345678\",\n \"city_destination_id\": \"01HXYZ123456789012345678\",\n \"district_destination_id\": \"01HXYZ123456789012345678\",\n \"subdistrict_destination_id\": \"01HXYZ123456789012345678\",\n \"postal_code_destination_id\": \"01HXYZ123456789012345678\",\n \"package_type_id\": \"01HXYZ123456789012345678\",\n \"moda_id\": \"01HXYZ123456789012345678\",\n \"lead_time\": \"2-3 days\",\n \"minimum_weight\": 1.0,\n \"merchant_id\": \"01HXYZ123456789012345678\",\n \"components\": [\n {\n \"id\": \"01HXYZ123456789012345678\",\n \"cost_component_id\": \"01HXYZ123456789012345678\",\n \"value\": \"15000\"\n }\n ]\n }\n}",rf:["name"]},
|
||||
{cat:"Basic Pricing",m:"put",p:"/basic-pricings/:id",s:"Update basic pricing",q:[{n:"id",t:"string",req:true,d:"Basic pricing ID"}],rb:"{\n \"province_source_id\": \"01HXYZ123456789012345678\",\n \"city_source_id\": \"01HXYZ123456789012345678\",\n \"district_source_id\": \"01HXYZ123456789012345678\",\n \"subdistrict_source_id\": \"01HXYZ123456789012345678\",\n \"postal_code_source_id\": \"01HXYZ123456789012345678\",\n \"province_destination_id\": \"01HXYZ123456789012345678\",\n \"city_destination_id\": \"01HXYZ123456789012345678\",\n \"district_destination_id\": \"01HXYZ123456789012345678\",\n \"subdistrict_destination_id\": \"01HXYZ123456789012345678\",\n \"postal_code_destination_id\": \"01HXYZ123456789012345678\",\n \"package_type_id\": \"01HXYZ123456789012345678\",\n \"moda_id\": \"01HXYZ123456789012345678\",\n \"lead_time\": \"2-3 days\",\n \"minimum_weight\": 1.0,\n \"components\": [\n {\n \"cost_component_id\": \"01HXYZ123456789012345678\",\n \"value\": \"15000\"\n }\n ]\n}",rbe:"{\n \"success\": true,\n \"data\": {\n \"id\": \"01HXYZ123456789012345678\",\n \"province_source_id\": \"01HXYZ123456789012345678\",\n \"city_source_id\": \"01HXYZ123456789012345678\",\n \"district_source_id\": \"01HXYZ123456789012345678\",\n \"subdistrict_source_id\": \"01HXYZ123456789012345678\",\n \"postal_code_source_id\": \"01HXYZ123456789012345678\",\n \"province_destination_id\": \"01HXYZ123456789012345678\",\n \"city_destination_id\": \"01HXYZ123456789012345678\",\n \"district_destination_id\": \"01HXYZ123456789012345678\",\n \"subdistrict_destination_id\": \"01HXYZ123456789012345678\",\n \"postal_code_destination_id\": \"01HXYZ123456789012345678\",\n \"package_type_id\": \"01HXYZ123456789012345678\",\n \"moda_id\": \"01HXYZ123456789012345678\",\n \"lead_time\": \"2-3 days\",\n \"minimum_weight\": 1.0,\n \"merchant_id\": \"01HXYZ123456789012345678\",\n \"components\": [\n {\n \"id\": \"01HXYZ123456789012345678\",\n \"cost_component_id\": \"01HXYZ123456789012345678\",\n \"value\": \"15000\"\n }\n ]\n }\n}",rf:["name"]},
|
||||
{cat:"Basic Pricing",m:"delete",p:"/basic-pricings/:id",s:"Delete basic pricing",q:[{n:"id",t:"string",req:true,d:"Basic pricing ID"}],rb:null,rbe:"{\n \"success\": true,\n \"message\": \"basic pricing deleted\"\n}",rf:[]},
|
||||
{cat:"Master Data / Package Type",m:"get",p:"/master-data/package-types/",s:"Get all package types",q:[{n:"id",t:"string",req:false,d:"Filter by ID"},{n:"name",t:"string",req:false,d:"Filter by name"},{n:"merchant_id",t:"string",req:false,d:"Filter by merchant"}],rb:null,rbe:"{\n \"success\": true,\n \"data\": [\n {\n \"id\": \"01HXYZ123456789012345678\",\n \"name\": \"Reguler\",\n \"merchant_id\": \"01HXYZ123456789012345678\"\n }\n ]\n}",rf:[]},
|
||||
{cat:"Master Data / Package Type",m:"post",p:"/master-data/package-types/list",s:"Package type list (DataTable)",q:[],rb:"_DT_",rbe:"{\n \"success\": true,\n \"data\": {\n \"draw\": 1,\n \"recordsTotal\": 10,\n \"recordsFiltered\": 10,\n \"data\": [\n { \"id\": \"01HXYZ123456789012345678\", \"name\": \"Reguler\" }\n ]\n }\n}",rf:[]},
|
||||
{cat:"Master Data / Package Type",m:"get",p:"/master-data/package-types/:id",s:"Get package type by ID",q:[{n:"id",t:"string",req:true,d:"Package type ID"}],rb:null,rbe:"{\n \"success\": true,\n \"data\": {\n \"id\": \"01HXYZ123456789012345678\",\n \"name\": \"Reguler\",\n \"merchant_id\": \"01HXYZ123456789012345678\"\n }\n}",rf:[]},
|
||||
{cat:"Master Data / Package Type",m:"post",p:"/master-data/package-types/",s:"Create package type",q:[],rb:"{\n \"name\": \"Reguler\"\n}",rbe:"{\n \"success\": true,\n \"data\": {\n \"id\": \"01HXYZ123456789012345678\",\n \"name\": \"Reguler\",\n \"merchant_id\": \"01HXYZ123456789012345678\"\n }\n}",rf:["name"]},
|
||||
{cat:"Master Data / Package Type",m:"put",p:"/master-data/package-types/:id",s:"Update package type",q:[{n:"id",t:"string",req:true,d:"Package type ID"}],rb:"{\n \"name\": \"Express\"\n}",rbe:"{\n \"success\": true,\n \"data\": {\n \"id\": \"01HXYZ123456789012345678\",\n \"name\": \"Express\",\n \"merchant_id\": \"01HXYZ123456789012345678\"\n }\n}",rf:["name"]},
|
||||
{cat:"Master Data / Package Type",m:"delete",p:"/master-data/package-types/:id",s:"Delete package type",q:[{n:"id",t:"string",req:true,d:"Package type ID"}],rb:null,rbe:"{\n \"success\": true,\n \"message\": \"package type deleted\"\n}",rf:[]},
|
||||
{cat:"Master Data / Moda",m:"get",p:"/master-data/modas/",s:"Get all modas",q:[{n:"id",t:"string",req:false,d:"Filter by ID"},{n:"name",t:"string",req:false,d:"Filter by name"},{n:"merchant_id",t:"string",req:false,d:"Filter by merchant"}],rb:null,rbe:"{\n \"success\": true,\n \"data\": [\n {\n \"id\": \"01HXYZ123456789012345678\",\n \"name\": \"Darat\",\n \"merchant_id\": \"01HXYZ123456789012345678\"\n }\n ]\n}",rf:[]},
|
||||
{cat:"Master Data / Moda",m:"post",p:"/master-data/modas/list",s:"Moda list (DataTable)",q:[],rb:"_DT_",rbe:"{\n \"success\": true,\n \"data\": {\n \"draw\": 1,\n \"recordsTotal\": 5,\n \"recordsFiltered\": 5,\n \"data\": [\n { \"id\": \"01HXYZ123456789012345678\", \"name\": \"Darat\" }\n ]\n }\n}",rf:[]},
|
||||
{cat:"Master Data / Moda",m:"get",p:"/master-data/modas/:id",s:"Get moda by ID",q:[{n:"id",t:"string",req:true,d:"Moda ID"}],rb:null,rbe:"{\n \"success\": true,\n \"data\": {\n \"id\": \"01HXYZ123456789012345678\",\n \"name\": \"Darat\",\n \"merchant_id\": \"01HXYZ123456789012345678\"\n }\n}",rf:[]},
|
||||
{cat:"Master Data / Moda",m:"post",p:"/master-data/modas/",s:"Create moda",q:[],rb:"{\n \"name\": \"Darat\"\n}",rbe:"{\n \"success\": true,\n \"data\": {\n \"id\": \"01HXYZ123456789012345678\",\n \"name\": \"Darat\",\n \"merchant_id\": \"01HXYZ123456789012345678\"\n }\n}",rf:["name"]},
|
||||
{cat:"Master Data / Moda",m:"put",p:"/master-data/modas/:id",s:"Update moda",q:[{n:"id",t:"string",req:true,d:"Moda ID"}],rb:"{\n \"name\": \"Udara\"\n}",rbe:"{\n \"success\": true,\n \"data\": {\n \"id\": \"01HXYZ123456789012345678\",\n \"name\": \"Udara\",\n \"merchant_id\": \"01HXYZ123456789012345678\"\n }\n}",rf:["name"]},
|
||||
{cat:"Master Data / Moda",m:"delete",p:"/master-data/modas/:id",s:"Delete moda",q:[{n:"id",t:"string",req:true,d:"Moda ID"}],rb:null,rbe:"{\n \"success\": true,\n \"message\": \"moda deleted\"\n}",rf:[]},
|
||||
{cat:"Activity Log",m:"get",p:"/activity-logs/",s:"Get all activity logs",q:[{n:"table_name",t:"string",req:false,d:"Filter by table name"},{n:"record_id",t:"string",req:false,d:"Filter by record ID"},{n:"action",t:"string",req:false,d:"Filter by action (CREATE, UPDATE, DELETE, REVERT)"},{n:"user_id",t:"string",req:false,d:"Filter by user ID"},{n:"date_from",t:"string",req:false,d:"Filter from date"},{n:"date_to",t:"string",req:false,d:"Filter to date"}],rb:null,rbe:"{\n \"success\": true,\n \"data\": [\n {\n \"id\": \"01HXYZ123456789012345678\",\n \"table_name\": \"province\",\n \"record_id\": \"01HXYZ123456789012345678\",\n \"action\": \"DELETE\",\n \"old_data\": \"{...}\",\n \"new_data\": null,\n \"cascade_data\": \"[{...}]\",\n \"user_id\": \"01HXYZ123456789012345678\",\n \"user_name\": \"Admin Utama\",\n \"created_on\": \"2026-09-05 10:30:00\",\n \"cascade_count\": 1102\n }\n ]\n}",rf:[]},
|
||||
{cat:"Activity Log",m:"post",p:"/activity-logs/list",s:"Activity log list (DataTable)",q:[],rb:"_DT_",rbe:"{\n \"success\": true,\n \"data\": {\n \"draw\": 1,\n \"recordsTotal\": 42,\n \"recordsFiltered\": 42,\n \"data\": []\n }\n}",rf:[]},
|
||||
{cat:"Activity Log",m:"get",p:"/activity-logs/:id",s:"Get activity log by ID",q:[{n:"id",t:"string",req:true,d:"Activity log ID"}],rb:null,rbe:"{\n \"success\": true,\n \"data\": {\n \"id\": \"01HXYZ123456789012345678\",\n \"table_name\": \"province\",\n \"record_id\": \"01HXYZ123456789012345678\",\n \"action\": \"DELETE\",\n \"old_data\": \"{...}\",\n \"cascade_data\": \"[{...}]\",\n \"user_id\": \"01HXYZ123456789012345678\",\n \"user_name\": \"Admin Utama\",\n \"created_on\": \"2026-09-05 10:30:00\",\n \"cascade_count\": 1102\n }\n}",rf:[]},
|
||||
{cat:"Activity Log",m:"post",p:"/activity-logs/:id/revert",s:"Revert activity log action",q:[{n:"id",t:"string",req:true,d:"Activity log ID"}],rb:null,rbe:"{\n \"success\": true,\n \"message\": \"action reverted successfully\"\n}",rf:["id"]}
|
||||
];
|
||||
function fmtMethod(m){return m.toUpperCase()}
|
||||
function methodColor(m){return{get:"var(--get)",post:"var(--post)",put:"var(--put)",delete:"var(--delete)"}[m]||"var(--text2)"}
|
||||
|
||||
@ -54,7 +54,10 @@ func (d *Database) Connect() {
|
||||
)
|
||||
d.AppLogger.Info("Connect To Master DB")
|
||||
gormLogger := logger.NewGormZapLogger(d.Logger, 5*time.Second)
|
||||
dbMaster, err := gorm.Open(postgres.Open(dsnMaster), &gorm.Config{
|
||||
dbMaster, err := gorm.Open(postgres.New(postgres.Config{
|
||||
DSN: dsnMaster,
|
||||
PreferSimpleProtocol: true,
|
||||
}), &gorm.Config{
|
||||
Logger: gormLogger,
|
||||
})
|
||||
if err != nil {
|
||||
@ -76,7 +79,10 @@ func (d *Database) Connect() {
|
||||
ssl_slave,
|
||||
)
|
||||
d.AppLogger.Info("Connect To Slave DB")
|
||||
dbSlave, err := gorm.Open(postgres.Open(dsnSlave), &gorm.Config{
|
||||
dbSlave, err := gorm.Open(postgres.New(postgres.Config{
|
||||
DSN: dsnSlave,
|
||||
PreferSimpleProtocol: true,
|
||||
}), &gorm.Config{
|
||||
Logger: gormLogger,
|
||||
})
|
||||
if err != nil {
|
||||
|
||||
23
internal/domain/activity_log.go
Normal file
23
internal/domain/activity_log.go
Normal file
@ -0,0 +1,23 @@
|
||||
package domain
|
||||
|
||||
import "time"
|
||||
|
||||
const TableNameActivityLogConst = "activity_log"
|
||||
|
||||
type ActivityLog struct {
|
||||
ID string `gorm:"column:id;type:character(26);primaryKey;default:generate_ulid()" json:"id"`
|
||||
TargetTable string `gorm:"column:table_name;type:character varying(100);not null" json:"table_name"`
|
||||
RecordID string `gorm:"column:record_id;type:character(26);not null" json:"record_id"`
|
||||
Action string `gorm:"column:action;type:character varying(20);not null" json:"action"`
|
||||
OldData *string `gorm:"column:old_data;type:jsonb" json:"old_data"`
|
||||
NewData *string `gorm:"column:new_data;type:jsonb" json:"new_data"`
|
||||
CascadeData *string `gorm:"column:cascade_data;type:jsonb" json:"cascade_data"`
|
||||
UserID string `gorm:"column:user_id;type:character(26);not null" json:"user_id"`
|
||||
UserName string `gorm:"column:user_name;type:character varying(255);not null" json:"user_name"`
|
||||
MerchantID *string `gorm:"column:merchant_id;type:character(26)" json:"merchant_id"`
|
||||
CreatedOn *time.Time `gorm:"column:created_on;type:timestamp without time zone;default:now()" json:"created_on"`
|
||||
}
|
||||
|
||||
func (*ActivityLog) TableName() string {
|
||||
return TableNameActivityLogConst
|
||||
}
|
||||
@ -10,7 +10,7 @@ const TableNameBasicPricingComponent = "basic_pricing_component"
|
||||
type BasicPricingComponent struct {
|
||||
ID string `gorm:"column:id;type:character(26);primaryKey;default:generate_ulid()" json:"id"`
|
||||
CostComponentID *string `gorm:"column:cost_component_id;type:character(26);index:basic_pricing_component_cost_component_id_idx,priority:1" json:"cost_component_id"`
|
||||
Value *float32 `gorm:"column:value;type:real" json:"value"`
|
||||
Value *string `gorm:"column:value;type:character varying(255)" json:"value"`
|
||||
BasicPricingID *string `gorm:"column:basic_pricing_id;type:character(26);index:basic_pricing_component_basic_pricing_id_idx,priority:1" json:"basic_pricing_id"`
|
||||
BasicPricing_Relation BasicPricing `gorm:"foreignKey:basic_pricing_id;references:id" json:"basic_pricing_relation"`
|
||||
CostComponent_Relation CostComponent `gorm:"foreignKey:cost_component_id;references:id" json:"cost_component_relation"`
|
||||
|
||||
@ -21,7 +21,7 @@ type PostalCode struct {
|
||||
CreatedBy *string `gorm:"column:created_by;type:character(26);index:postal_code_created_by_idx,priority:1" json:"created_by"`
|
||||
CreatedOn *time.Time `gorm:"column:created_on;type:timestamp without time zone" json:"created_on"`
|
||||
UpdatedBy *string `gorm:"column:updated_by;type:character(26)" json:"updated_by"`
|
||||
UpdatedOn *time.Time `gorm:"column:updated_on;type:timestamp without time zone" json:"updated_on"`
|
||||
UpdatedOn *string `gorm:"column:updated_on;type:character varying" json:"updated_on"`
|
||||
MerchantID *string `gorm:"column:merchant_id;type:character(26)" json:"merchant_id"`
|
||||
BasicPricing_ByPostalCodeDestination_Relation []BasicPricing `gorm:"foreignKey:postal_code_destination_id;references:id" json:"basic_pricing_by_postal_code_destination_relation"`
|
||||
BasicPricing_ByPostalCodeSource_Relation []BasicPricing `gorm:"foreignKey:postal_code_source_id;references:id" json:"basic_pricing_by_postal_code_source_relation"`
|
||||
|
||||
27
internal/handlers/dto/activity_log.go
Normal file
27
internal/handlers/dto/activity_log.go
Normal file
@ -0,0 +1,27 @@
|
||||
package dto
|
||||
|
||||
type ActivityLogFilterRequest struct {
|
||||
ID string `json:"id" form:"id"`
|
||||
TableName string `json:"table_name" form:"table_name"`
|
||||
RecordID string `json:"record_id" form:"record_id"`
|
||||
Action string `json:"action" form:"action"`
|
||||
UserID string `json:"user_id" form:"user_id"`
|
||||
MerchantID string `json:"merchant_id" form:"merchant_id"`
|
||||
DateFrom string `json:"date_from" form:"date_from"`
|
||||
DateTo string `json:"date_to" form:"date_to"`
|
||||
}
|
||||
|
||||
type ActivityLogResponse struct {
|
||||
ID string `json:"id"`
|
||||
TableName string `json:"table_name"`
|
||||
RecordID string `json:"record_id"`
|
||||
Action string `json:"action"`
|
||||
OldData *string `json:"old_data"`
|
||||
NewData *string `json:"new_data"`
|
||||
CascadeData *string `json:"cascade_data"`
|
||||
UserID string `json:"user_id"`
|
||||
UserName string `json:"user_name"`
|
||||
MerchantID *string `json:"merchant_id"`
|
||||
CreatedOn *string `json:"created_on"`
|
||||
CascadeCount int `json:"cascade_count,omitempty"`
|
||||
}
|
||||
@ -2,13 +2,13 @@ package dto
|
||||
|
||||
type BasicPricingComponentRequest struct {
|
||||
CostComponentID string `json:"cost_component_id" binding:"required"`
|
||||
Value float32 `json:"value"`
|
||||
Value string `json:"value"`
|
||||
}
|
||||
|
||||
type BasicPricingComponentResponse struct {
|
||||
ID string `json:"id"`
|
||||
CostComponentID *string `json:"cost_component_id"`
|
||||
Value *float32 `json:"value"`
|
||||
Value *string `json:"value"`
|
||||
}
|
||||
|
||||
type CreateBasicPricingRequest struct {
|
||||
@ -24,8 +24,8 @@ type CreateBasicPricingRequest struct {
|
||||
PostalCodeDestinationID string `json:"postal_code_destination_id" binding:"required"`
|
||||
PackageTypeID string `json:"package_type_id" binding:"required"`
|
||||
ModaID string `json:"moda_id" binding:"required"`
|
||||
LeadTime string `json:"lead_time"`
|
||||
MinimumWeight float32 `json:"minimum_weight"`
|
||||
LeadTime string `json:"lead_time" binding:"required"`
|
||||
MinimumWeight float32 `json:"minimum_weight" binding:"required"`
|
||||
Components []BasicPricingComponentRequest `json:"components" binding:"required,dive"`
|
||||
}
|
||||
|
||||
@ -65,3 +65,7 @@ type BasicPricingFilterAllRequest struct {
|
||||
ModaID string `json:"moda_id" form:"moda_id"`
|
||||
MerchantID string `json:"merchant_id" form:"merchant_id"`
|
||||
}
|
||||
|
||||
type BasicPricingMatchRequest struct {
|
||||
ID string `json:"id" form:"id" binding:"required"`
|
||||
}
|
||||
|
||||
21
internal/handlers/dto/moda.go
Normal file
21
internal/handlers/dto/moda.go
Normal file
@ -0,0 +1,21 @@
|
||||
package dto
|
||||
|
||||
type CreateModaRequest struct {
|
||||
Name string `json:"name" binding:"required,min=2"`
|
||||
}
|
||||
|
||||
type CreateModaResponse struct {
|
||||
ID string `json:"id"`
|
||||
Name *string `json:"name"`
|
||||
MerchantID *string `json:"merchant_id"`
|
||||
}
|
||||
|
||||
type ModaFilterAllRequest struct {
|
||||
ID string `json:"id" form:"id"`
|
||||
Name string `json:"name" form:"name"`
|
||||
MerchantID string `json:"merchant_id" form:"merchant_id"`
|
||||
}
|
||||
|
||||
type UpdateModaRequest struct {
|
||||
Name string `json:"name" binding:"required,min=2"`
|
||||
}
|
||||
21
internal/handlers/dto/package_type.go
Normal file
21
internal/handlers/dto/package_type.go
Normal file
@ -0,0 +1,21 @@
|
||||
package dto
|
||||
|
||||
type CreatePackageTypeRequest struct {
|
||||
Name string `json:"name" binding:"required,min=2"`
|
||||
}
|
||||
|
||||
type CreatePackageTypeResponse struct {
|
||||
ID string `json:"id"`
|
||||
Name *string `json:"name"`
|
||||
MerchantID *string `json:"merchant_id"`
|
||||
}
|
||||
|
||||
type PackageTypeFilterAllRequest struct {
|
||||
ID string `json:"id" form:"id"`
|
||||
Name string `json:"name" form:"name"`
|
||||
MerchantID string `json:"merchant_id" form:"merchant_id"`
|
||||
}
|
||||
|
||||
type UpdatePackageTypeRequest struct {
|
||||
Name string `json:"name" binding:"required,min=2"`
|
||||
}
|
||||
@ -1,18 +1,24 @@
|
||||
package handlers
|
||||
|
||||
import (
|
||||
"cargo-erp-backend/internal/handlers/router/activity_log"
|
||||
"cargo-erp-backend/internal/handlers/router/auth"
|
||||
"cargo-erp-backend/internal/handlers/router/basic_pricing"
|
||||
"cargo-erp-backend/internal/handlers/router/city"
|
||||
"cargo-erp-backend/internal/handlers/router/cost_component"
|
||||
"cargo-erp-backend/internal/handlers/router/district"
|
||||
"cargo-erp-backend/internal/handlers/router/moda"
|
||||
"cargo-erp-backend/internal/handlers/router/package_type"
|
||||
"cargo-erp-backend/internal/handlers/router/postal_code"
|
||||
"cargo-erp-backend/internal/handlers/router/province"
|
||||
"cargo-erp-backend/internal/handlers/router/subdistrict"
|
||||
"cargo-erp-backend/internal/middleware"
|
||||
"cargo-erp-backend/pkg/helpers"
|
||||
"cargo-erp-backend/internal/usecases"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"time"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
@ -108,6 +114,13 @@ func (h *Handlers) Run() {
|
||||
"message": "pong",
|
||||
})
|
||||
})
|
||||
|
||||
// serve API docs (no auth)
|
||||
docsPath := filepath.Join(".", "..", "..", "docs")
|
||||
if _, err := os.Stat(docsPath); err == nil {
|
||||
r.Static("/docs", docsPath)
|
||||
}
|
||||
|
||||
//auth
|
||||
auth.NewAuthHandler(h.Helper, r).Router()
|
||||
|
||||
@ -122,6 +135,8 @@ func (h *Handlers) Run() {
|
||||
subdistrict.NewSubdistrictHandler(h.Helper, masterdata).Router()
|
||||
postal_code.NewPostalCodeHandler(h.Helper, masterdata).Router()
|
||||
cost_component.NewCostComponentHandler(h.Helper, masterdata).Router()
|
||||
package_type.NewPackageTypeHandler(h.Helper, masterdata).Router()
|
||||
moda.NewModaHandler(h.Helper, masterdata).Router()
|
||||
}
|
||||
|
||||
//basic-pricing
|
||||
@ -129,6 +144,19 @@ func (h *Handlers) Run() {
|
||||
basicPricingGroup.Use(middleware.NewAuthMiddleware(h.Helper).Check())
|
||||
basic_pricing.NewBasicPricingHandler(h.Helper, basicPricingGroup).Router()
|
||||
|
||||
//activity-logs
|
||||
activityLogGroup := r.Group("activity-logs")
|
||||
activityLogGroup.Use(middleware.NewAuthMiddleware(h.Helper).Check())
|
||||
activity_log.NewActivityLogHandler(h.Helper, activityLogGroup).Router()
|
||||
|
||||
// load cascade rules from DB
|
||||
db := h.Helper.GetDB("master")
|
||||
if err := usecases.LoadCascadeRules(db); err != nil {
|
||||
h.Helper.Log().Error("failed to load cascade rules", zap.Error(err))
|
||||
} else {
|
||||
h.Helper.Log().Info("Cascade rules loaded from database")
|
||||
}
|
||||
|
||||
h.Helper.Log().Info("Starting Apps")
|
||||
r.Run(fmt.Sprintf("%v:%v", host, port))
|
||||
}
|
||||
|
||||
119
internal/handlers/router/activity_log/activity_log.go
Normal file
119
internal/handlers/router/activity_log/activity_log.go
Normal file
@ -0,0 +1,119 @@
|
||||
package activity_log
|
||||
|
||||
import (
|
||||
"cargo-erp-backend/internal/handlers/dto"
|
||||
"cargo-erp-backend/internal/usecases"
|
||||
"cargo-erp-backend/pkg/helpers"
|
||||
"cargo-erp-backend/pkg/response"
|
||||
"net/http"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
type ActivityLogHandlerInterface interface {
|
||||
Router()
|
||||
}
|
||||
|
||||
type ActivityLogHandler struct {
|
||||
Helper helpers.HelperInterface
|
||||
Group *gin.RouterGroup
|
||||
}
|
||||
|
||||
func NewActivityLogHandler(helper helpers.HelperInterface, g *gin.RouterGroup) ActivityLogHandlerInterface {
|
||||
return &ActivityLogHandler{Helper: helper, Group: g}
|
||||
}
|
||||
|
||||
func (h *ActivityLogHandler) Router() {
|
||||
r := h.Group
|
||||
{
|
||||
r.GET("/", h.GetAll)
|
||||
r.POST("/list", h.GetList)
|
||||
r.GET("/:id", h.GetByID)
|
||||
r.POST("/:id/revert", h.Revert)
|
||||
}
|
||||
}
|
||||
|
||||
func (h *ActivityLogHandler) GetAll(c *gin.Context) {
|
||||
userid, err := h.Helper.GetAuthInfo(c.GetString("auth"))
|
||||
if err != nil {
|
||||
response.Error(c, http.StatusUnauthorized, err.Error())
|
||||
return
|
||||
}
|
||||
var req dto.ActivityLogFilterRequest
|
||||
if err := c.ShouldBindQuery(&req); err != nil {
|
||||
response.Error(c, http.StatusBadRequest, err.Error())
|
||||
return
|
||||
}
|
||||
u := usecases.NewActivityLogUsecase(h.Helper, *userid)
|
||||
logs, _, err := u.GetAll(req)
|
||||
if err != nil {
|
||||
response.Error(c, http.StatusInternalServerError, err.Error())
|
||||
return
|
||||
}
|
||||
response.Success(c, logs)
|
||||
}
|
||||
|
||||
func (h *ActivityLogHandler) GetList(c *gin.Context) {
|
||||
userid, err := h.Helper.GetAuthInfo(c.GetString("auth"))
|
||||
if err != nil {
|
||||
response.Error(c, http.StatusUnauthorized, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
var req dto.DataTableRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
response.Error(c, http.StatusBadRequest, "Request Format request invalid")
|
||||
return
|
||||
}
|
||||
u := usecases.NewActivityLogUsecase(h.Helper, *userid)
|
||||
res, err := u.GetList(req)
|
||||
if err != nil {
|
||||
response.Error(c, http.StatusInternalServerError, err.Error())
|
||||
return
|
||||
}
|
||||
response.Success(c, res)
|
||||
}
|
||||
|
||||
func (h *ActivityLogHandler) GetByID(c *gin.Context) {
|
||||
userid, err := h.Helper.GetAuthInfo(c.GetString("auth"))
|
||||
if err != nil {
|
||||
response.Error(c, http.StatusUnauthorized, err.Error())
|
||||
return
|
||||
}
|
||||
id := c.Param("id")
|
||||
|
||||
u := usecases.NewActivityLogUsecase(h.Helper, *userid)
|
||||
log, err := u.GetByID(id)
|
||||
if err != nil {
|
||||
response.Error(c, http.StatusNotFound, "activity log not found")
|
||||
return
|
||||
}
|
||||
|
||||
response.Success(c, log)
|
||||
}
|
||||
|
||||
func (h *ActivityLogHandler) Revert(c *gin.Context) {
|
||||
userid, err := h.Helper.GetAuthInfo(c.GetString("auth"))
|
||||
if err != nil {
|
||||
response.Error(c, http.StatusUnauthorized, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
roleKey := ""
|
||||
if userid.UsersRole_Relation != nil {
|
||||
roleKey = userid.UsersRole_Relation.RoleKey
|
||||
}
|
||||
if roleKey != "SPM" {
|
||||
response.Error(c, http.StatusForbidden, "only Super Admin can revert")
|
||||
return
|
||||
}
|
||||
|
||||
id := c.Param("id")
|
||||
u := usecases.NewActivityLogUsecase(h.Helper, *userid)
|
||||
if err := u.Revert(id); err != nil {
|
||||
response.Error(c, http.StatusInternalServerError, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
response.Success(c, map[string]interface{}{"message": "action reverted successfully"})
|
||||
}
|
||||
@ -29,6 +29,7 @@ func (h *BasicPricingHandler) Router() {
|
||||
r.GET("/", h.GetAll)
|
||||
r.POST("/list", h.GetList)
|
||||
r.GET("/:id", h.GetByID)
|
||||
r.POST("/match", h.GetMatch)
|
||||
r.POST("/", h.Create)
|
||||
r.PUT("/:id", h.Update)
|
||||
r.DELETE("/:id", h.Delete)
|
||||
@ -160,3 +161,24 @@ func (h *BasicPricingHandler) Delete(c *gin.Context) {
|
||||
|
||||
response.Success(c, map[string]interface{}{"message": "basic pricing deleted"})
|
||||
}
|
||||
|
||||
func (h *BasicPricingHandler) GetMatch(c *gin.Context) {
|
||||
var req dto.BasicPricingMatchRequest
|
||||
if err := c.BindJSON(&req); err != nil {
|
||||
response.Error(c, http.StatusBadRequest, err.Error())
|
||||
return
|
||||
}
|
||||
userid, err := h.Helper.GetAuthInfo(c.GetString("auth"))
|
||||
if err != nil {
|
||||
response.Error(c, http.StatusUnauthorized, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
u := usecases.NewBasicPricingUsecase(h.Helper, *userid)
|
||||
pricing := u.GetMatch(req.ID)
|
||||
if pricing == nil {
|
||||
response.Error(c, http.StatusNotFound, "basic pricing not found")
|
||||
return
|
||||
}
|
||||
response.Success(c, pricing)
|
||||
}
|
||||
|
||||
172
internal/handlers/router/moda/moda.go
Normal file
172
internal/handlers/router/moda/moda.go
Normal file
@ -0,0 +1,172 @@
|
||||
package moda
|
||||
|
||||
import (
|
||||
"cargo-erp-backend/internal/handlers/dto"
|
||||
"cargo-erp-backend/internal/usecases"
|
||||
"cargo-erp-backend/pkg/helpers"
|
||||
"cargo-erp-backend/pkg/response"
|
||||
"net/http"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
type ModaHandlerInterface interface {
|
||||
Router()
|
||||
}
|
||||
|
||||
type ModaHandler struct {
|
||||
Helper helpers.HelperInterface
|
||||
Group *gin.RouterGroup
|
||||
}
|
||||
|
||||
func NewModaHandler(helper helpers.HelperInterface, g *gin.RouterGroup) ModaHandlerInterface {
|
||||
return &ModaHandler{Helper: helper, Group: g}
|
||||
}
|
||||
|
||||
func (h *ModaHandler) Router() {
|
||||
r := h.Group.Group("modas")
|
||||
{
|
||||
r.GET("/", h.GetAll)
|
||||
r.POST("/list", h.GetList)
|
||||
r.GET("/:id", h.GetByID)
|
||||
r.POST("/", h.Create)
|
||||
r.PUT("/:id", h.Update)
|
||||
r.DELETE("/:id", h.Delete)
|
||||
}
|
||||
}
|
||||
|
||||
func (h *ModaHandler) GetAll(c *gin.Context) {
|
||||
userid, err := h.Helper.GetAuthInfo(c.GetString("auth"))
|
||||
if err != nil {
|
||||
response.Error(c, http.StatusUnauthorized, err.Error())
|
||||
return
|
||||
}
|
||||
var req dto.ModaFilterAllRequest
|
||||
if err := c.ShouldBindQuery(&req); err != nil {
|
||||
response.Error(c, http.StatusBadRequest, err.Error())
|
||||
return
|
||||
}
|
||||
u := usecases.NewModaUsecase(h.Helper, *userid)
|
||||
items, _, err := u.GetAll(req)
|
||||
if err != nil {
|
||||
response.Error(c, http.StatusInternalServerError, err.Error())
|
||||
return
|
||||
}
|
||||
var responseDTO = make([]dto.CreateModaResponse, 0)
|
||||
for _, v := range items {
|
||||
var DTO dto.CreateModaResponse
|
||||
h.Helper.MapStructToStruct(v, "json", &DTO, "json")
|
||||
responseDTO = append(responseDTO, DTO)
|
||||
}
|
||||
response.Success(c, responseDTO)
|
||||
}
|
||||
|
||||
func (h *ModaHandler) GetList(c *gin.Context) {
|
||||
userid, err := h.Helper.GetAuthInfo(c.GetString("auth"))
|
||||
if err != nil {
|
||||
response.Error(c, http.StatusUnauthorized, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
var req dto.DataTableRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
response.Error(c, http.StatusBadRequest, "Request Format request invalid")
|
||||
return
|
||||
}
|
||||
u := usecases.NewModaUsecase(h.Helper, *userid)
|
||||
res, err := u.GetList(req)
|
||||
if err != nil {
|
||||
response.Error(c, http.StatusInternalServerError, err.Error())
|
||||
return
|
||||
}
|
||||
response.Success(c, res)
|
||||
return
|
||||
}
|
||||
|
||||
func (h *ModaHandler) GetByID(c *gin.Context) {
|
||||
userid, err := h.Helper.GetAuthInfo(c.GetString("auth"))
|
||||
if err != nil {
|
||||
response.Error(c, http.StatusUnauthorized, err.Error())
|
||||
return
|
||||
}
|
||||
id := c.Param("id")
|
||||
|
||||
u := usecases.NewModaUsecase(h.Helper, *userid)
|
||||
item, err := u.GetByID(id)
|
||||
if err != nil {
|
||||
response.Error(c, http.StatusNotFound, "moda not found")
|
||||
return
|
||||
}
|
||||
|
||||
response.Success(c, item)
|
||||
}
|
||||
|
||||
func (h *ModaHandler) Create(c *gin.Context) {
|
||||
var req dto.CreateModaRequest
|
||||
if err := c.BindJSON(&req); err != nil {
|
||||
response.Error(c, http.StatusBadRequest, err.Error())
|
||||
return
|
||||
}
|
||||
userid, err := h.Helper.GetAuthInfo(c.GetString("auth"))
|
||||
if err != nil {
|
||||
response.Error(c, http.StatusUnauthorized, err.Error())
|
||||
return
|
||||
}
|
||||
var merchantid *string = nil
|
||||
if userid.UsersRole_Relation == nil || userid.UsersRole_Relation.RoleKey != "SPM" {
|
||||
merchantid = userid.MerchantID
|
||||
}
|
||||
createdBy := userid.ID
|
||||
|
||||
u := usecases.NewModaUsecase(h.Helper, *userid)
|
||||
item, err := u.Create(req.Name, createdBy, merchantid)
|
||||
if err != nil {
|
||||
response.Error(c, http.StatusInternalServerError, err.Error())
|
||||
return
|
||||
}
|
||||
var responseDTO dto.CreateModaResponse
|
||||
h.Helper.MapStructToStruct(item, "json", &responseDTO, "json")
|
||||
response.Created(c, responseDTO)
|
||||
}
|
||||
|
||||
func (h *ModaHandler) Update(c *gin.Context) {
|
||||
id := c.Param("id")
|
||||
|
||||
var req dto.UpdateModaRequest
|
||||
if err := c.BindJSON(&req); err != nil {
|
||||
response.Error(c, http.StatusBadRequest, err.Error())
|
||||
return
|
||||
}
|
||||
userid, err := h.Helper.GetAuthInfo(c.GetString("auth"))
|
||||
if err != nil {
|
||||
response.Error(c, http.StatusUnauthorized, err.Error())
|
||||
return
|
||||
}
|
||||
updatedBy := userid.ID
|
||||
|
||||
u := usecases.NewModaUsecase(h.Helper, *userid)
|
||||
item, err := u.Update(id, req.Name, updatedBy)
|
||||
if err != nil {
|
||||
response.Error(c, http.StatusInternalServerError, err.Error())
|
||||
return
|
||||
}
|
||||
var responseDTO dto.CreateModaResponse
|
||||
h.Helper.MapStructToStruct(item, "json", &responseDTO, "json")
|
||||
response.Success(c, responseDTO)
|
||||
}
|
||||
|
||||
func (h *ModaHandler) Delete(c *gin.Context) {
|
||||
userid, err := h.Helper.GetAuthInfo(c.GetString("auth"))
|
||||
if err != nil {
|
||||
response.Error(c, http.StatusUnauthorized, err.Error())
|
||||
return
|
||||
}
|
||||
id := c.Param("id")
|
||||
u := usecases.NewModaUsecase(h.Helper, *userid)
|
||||
if err := u.Delete(id); err != nil {
|
||||
response.Error(c, http.StatusInternalServerError, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
response.Success(c, map[string]interface{}{"message": "moda deleted"})
|
||||
}
|
||||
172
internal/handlers/router/package_type/package_type.go
Normal file
172
internal/handlers/router/package_type/package_type.go
Normal file
@ -0,0 +1,172 @@
|
||||
package package_type
|
||||
|
||||
import (
|
||||
"cargo-erp-backend/internal/handlers/dto"
|
||||
"cargo-erp-backend/internal/usecases"
|
||||
"cargo-erp-backend/pkg/helpers"
|
||||
"cargo-erp-backend/pkg/response"
|
||||
"net/http"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
type PackageTypeHandlerInterface interface {
|
||||
Router()
|
||||
}
|
||||
|
||||
type PackageTypeHandler struct {
|
||||
Helper helpers.HelperInterface
|
||||
Group *gin.RouterGroup
|
||||
}
|
||||
|
||||
func NewPackageTypeHandler(helper helpers.HelperInterface, g *gin.RouterGroup) PackageTypeHandlerInterface {
|
||||
return &PackageTypeHandler{Helper: helper, Group: g}
|
||||
}
|
||||
|
||||
func (h *PackageTypeHandler) Router() {
|
||||
r := h.Group.Group("package-types")
|
||||
{
|
||||
r.GET("/", h.GetAll)
|
||||
r.POST("/list", h.GetList)
|
||||
r.GET("/:id", h.GetByID)
|
||||
r.POST("/", h.Create)
|
||||
r.PUT("/:id", h.Update)
|
||||
r.DELETE("/:id", h.Delete)
|
||||
}
|
||||
}
|
||||
|
||||
func (h *PackageTypeHandler) GetAll(c *gin.Context) {
|
||||
userid, err := h.Helper.GetAuthInfo(c.GetString("auth"))
|
||||
if err != nil {
|
||||
response.Error(c, http.StatusUnauthorized, err.Error())
|
||||
return
|
||||
}
|
||||
var req dto.PackageTypeFilterAllRequest
|
||||
if err := c.ShouldBindQuery(&req); err != nil {
|
||||
response.Error(c, http.StatusBadRequest, err.Error())
|
||||
return
|
||||
}
|
||||
u := usecases.NewPackageTypeUsecase(h.Helper, *userid)
|
||||
items, _, err := u.GetAll(req)
|
||||
if err != nil {
|
||||
response.Error(c, http.StatusInternalServerError, err.Error())
|
||||
return
|
||||
}
|
||||
var responseDTO = make([]dto.CreatePackageTypeResponse, 0)
|
||||
for _, v := range items {
|
||||
var DTO dto.CreatePackageTypeResponse
|
||||
h.Helper.MapStructToStruct(v, "json", &DTO, "json")
|
||||
responseDTO = append(responseDTO, DTO)
|
||||
}
|
||||
response.Success(c, responseDTO)
|
||||
}
|
||||
|
||||
func (h *PackageTypeHandler) GetList(c *gin.Context) {
|
||||
userid, err := h.Helper.GetAuthInfo(c.GetString("auth"))
|
||||
if err != nil {
|
||||
response.Error(c, http.StatusUnauthorized, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
var req dto.DataTableRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
response.Error(c, http.StatusBadRequest, "Request Format request invalid")
|
||||
return
|
||||
}
|
||||
u := usecases.NewPackageTypeUsecase(h.Helper, *userid)
|
||||
res, err := u.GetList(req)
|
||||
if err != nil {
|
||||
response.Error(c, http.StatusInternalServerError, err.Error())
|
||||
return
|
||||
}
|
||||
response.Success(c, res)
|
||||
return
|
||||
}
|
||||
|
||||
func (h *PackageTypeHandler) GetByID(c *gin.Context) {
|
||||
userid, err := h.Helper.GetAuthInfo(c.GetString("auth"))
|
||||
if err != nil {
|
||||
response.Error(c, http.StatusUnauthorized, err.Error())
|
||||
return
|
||||
}
|
||||
id := c.Param("id")
|
||||
|
||||
u := usecases.NewPackageTypeUsecase(h.Helper, *userid)
|
||||
item, err := u.GetByID(id)
|
||||
if err != nil {
|
||||
response.Error(c, http.StatusNotFound, "package type not found")
|
||||
return
|
||||
}
|
||||
|
||||
response.Success(c, item)
|
||||
}
|
||||
|
||||
func (h *PackageTypeHandler) Create(c *gin.Context) {
|
||||
var req dto.CreatePackageTypeRequest
|
||||
if err := c.BindJSON(&req); err != nil {
|
||||
response.Error(c, http.StatusBadRequest, err.Error())
|
||||
return
|
||||
}
|
||||
userid, err := h.Helper.GetAuthInfo(c.GetString("auth"))
|
||||
if err != nil {
|
||||
response.Error(c, http.StatusUnauthorized, err.Error())
|
||||
return
|
||||
}
|
||||
var merchantid *string = nil
|
||||
if userid.UsersRole_Relation == nil || userid.UsersRole_Relation.RoleKey != "SPM" {
|
||||
merchantid = userid.MerchantID
|
||||
}
|
||||
createdBy := userid.ID
|
||||
|
||||
u := usecases.NewPackageTypeUsecase(h.Helper, *userid)
|
||||
item, err := u.Create(req.Name, createdBy, merchantid)
|
||||
if err != nil {
|
||||
response.Error(c, http.StatusInternalServerError, err.Error())
|
||||
return
|
||||
}
|
||||
var responseDTO dto.CreatePackageTypeResponse
|
||||
h.Helper.MapStructToStruct(item, "json", &responseDTO, "json")
|
||||
response.Created(c, responseDTO)
|
||||
}
|
||||
|
||||
func (h *PackageTypeHandler) Update(c *gin.Context) {
|
||||
id := c.Param("id")
|
||||
|
||||
var req dto.UpdatePackageTypeRequest
|
||||
if err := c.BindJSON(&req); err != nil {
|
||||
response.Error(c, http.StatusBadRequest, err.Error())
|
||||
return
|
||||
}
|
||||
userid, err := h.Helper.GetAuthInfo(c.GetString("auth"))
|
||||
if err != nil {
|
||||
response.Error(c, http.StatusUnauthorized, err.Error())
|
||||
return
|
||||
}
|
||||
updatedBy := userid.ID
|
||||
|
||||
u := usecases.NewPackageTypeUsecase(h.Helper, *userid)
|
||||
item, err := u.Update(id, req.Name, updatedBy)
|
||||
if err != nil {
|
||||
response.Error(c, http.StatusInternalServerError, err.Error())
|
||||
return
|
||||
}
|
||||
var responseDTO dto.CreatePackageTypeResponse
|
||||
h.Helper.MapStructToStruct(item, "json", &responseDTO, "json")
|
||||
response.Success(c, responseDTO)
|
||||
}
|
||||
|
||||
func (h *PackageTypeHandler) Delete(c *gin.Context) {
|
||||
userid, err := h.Helper.GetAuthInfo(c.GetString("auth"))
|
||||
if err != nil {
|
||||
response.Error(c, http.StatusUnauthorized, err.Error())
|
||||
return
|
||||
}
|
||||
id := c.Param("id")
|
||||
u := usecases.NewPackageTypeUsecase(h.Helper, *userid)
|
||||
if err := u.Delete(id); err != nil {
|
||||
response.Error(c, http.StatusInternalServerError, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
response.Success(c, map[string]interface{}{"message": "package type deleted"})
|
||||
}
|
||||
@ -97,6 +97,7 @@ func (h *PostalCodeImportHandler) ValidateRow(row []string, rowNumber int) (impo
|
||||
h.lastSubdistrictName = subdistrictName
|
||||
|
||||
now := time.Now()
|
||||
nowStr := now.Format("2006-01-02 15:04:05.999999-07:00")
|
||||
pc := &domain.PostalCode{
|
||||
PostalCode: &postalCode,
|
||||
ProvinceID: &province.ID,
|
||||
@ -107,7 +108,7 @@ func (h *PostalCodeImportHandler) ValidateRow(row []string, rowNumber int) (impo
|
||||
CreatedBy: &h.UserData.ID,
|
||||
CreatedOn: &now,
|
||||
UpdatedBy: &h.UserData.ID,
|
||||
UpdatedOn: &now,
|
||||
UpdatedOn: &nowStr,
|
||||
}
|
||||
|
||||
return pc, nil
|
||||
|
||||
500
internal/usecases/activity_log.go
Normal file
500
internal/usecases/activity_log.go
Normal file
@ -0,0 +1,500 @@
|
||||
package usecases
|
||||
|
||||
import (
|
||||
"cargo-erp-backend/internal/domain"
|
||||
"cargo-erp-backend/internal/handlers/dto"
|
||||
"cargo-erp-backend/pkg/datatable"
|
||||
"cargo-erp-backend/pkg/helpers"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"go.uber.org/zap"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
type CascadeRule struct {
|
||||
Table string
|
||||
FKColumn string
|
||||
DeleteRule string
|
||||
}
|
||||
|
||||
type CascadeGroup struct {
|
||||
Table string `json:"table"`
|
||||
FKColumn string `json:"fk_column"`
|
||||
DeleteRule string `json:"delete_rule"`
|
||||
Records []map[string]interface{} `json:"records"`
|
||||
}
|
||||
|
||||
var (
|
||||
CascadeMap map[string][]CascadeRule
|
||||
CascadeMapMu sync.RWMutex
|
||||
)
|
||||
|
||||
type ActivityLogUsecaseInterface interface {
|
||||
GetAll(filter dto.ActivityLogFilterRequest) ([]dto.ActivityLogResponse, int64, error)
|
||||
GetList(req dto.DataTableRequest) (dto.DataTableResponse, error)
|
||||
GetByID(id string) (dto.ActivityLogResponse, error)
|
||||
Revert(logID string) error
|
||||
LogCreate(tableName string, record interface{}, merchantID *string)
|
||||
LogUpdate(tableName string, oldData, newData interface{}, merchantID *string)
|
||||
LogDelete(tableName string, recordID string, oldData interface{}, merchantID *string)
|
||||
}
|
||||
|
||||
type ActivityLogUsecase struct {
|
||||
Helper helpers.HelperInterface
|
||||
AuthUser domain.User
|
||||
}
|
||||
|
||||
func NewActivityLogUsecase(helper helpers.HelperInterface, authUser domain.User) ActivityLogUsecaseInterface {
|
||||
return &ActivityLogUsecase{Helper: helper, AuthUser: authUser}
|
||||
}
|
||||
|
||||
func LoadCascadeRules(db *gorm.DB) error {
|
||||
rows, err := db.Raw(`
|
||||
SELECT
|
||||
tc.table_name AS source_table,
|
||||
kcu.column_name AS source_column,
|
||||
ccu.table_name AS target_table,
|
||||
ccu.column_name AS target_column,
|
||||
rc.delete_rule
|
||||
FROM information_schema.table_constraints tc
|
||||
JOIN information_schema.key_column_usage kcu
|
||||
ON tc.constraint_name = kcu.constraint_name AND tc.table_schema = kcu.table_schema
|
||||
JOIN information_schema.constraint_column_usage ccu
|
||||
ON ccu.constraint_name = tc.constraint_name AND ccu.table_schema = ccu.table_schema
|
||||
JOIN information_schema.referential_constraints rc
|
||||
ON rc.constraint_name = tc.constraint_name AND rc.constraint_schema = tc.table_schema
|
||||
WHERE tc.constraint_type = 'FOREIGN KEY'
|
||||
AND tc.table_schema = 'public'
|
||||
ORDER BY tc.table_name
|
||||
`).Rows()
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to query FK constraints: %w", err)
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
newMap := make(map[string][]CascadeRule)
|
||||
for rows.Next() {
|
||||
var fk ForeignKeyInfo
|
||||
if err := rows.Scan(&fk.SourceTable, &fk.SourceColumn, &fk.TargetTable, &fk.TargetColumn, &fk.DeleteRule); err != nil {
|
||||
continue
|
||||
}
|
||||
if _, ok := newMap[fk.TargetTable]; !ok {
|
||||
newMap[fk.TargetTable] = make([]CascadeRule, 0)
|
||||
}
|
||||
newMap[fk.TargetTable] = append(newMap[fk.TargetTable], CascadeRule{
|
||||
Table: fk.SourceTable,
|
||||
FKColumn: fk.SourceColumn,
|
||||
DeleteRule: fk.DeleteRule,
|
||||
})
|
||||
}
|
||||
|
||||
CascadeMapMu.Lock()
|
||||
CascadeMap = newMap
|
||||
CascadeMapMu.Unlock()
|
||||
return nil
|
||||
}
|
||||
|
||||
type ForeignKeyInfo struct {
|
||||
SourceTable string
|
||||
SourceColumn string
|
||||
TargetTable string
|
||||
TargetColumn string
|
||||
DeleteRule string
|
||||
}
|
||||
|
||||
func CaptureCascade(tx *gorm.DB, tableName string, recordID string) ([]CascadeGroup, error) {
|
||||
groups := make([]CascadeGroup, 0)
|
||||
visited := make(map[string]bool)
|
||||
|
||||
CascadeMapMu.RLock()
|
||||
defer CascadeMapMu.RUnlock()
|
||||
|
||||
var walk func(table string, ids []string)
|
||||
walk = func(table string, ids []string) {
|
||||
if len(ids) == 0 {
|
||||
return
|
||||
}
|
||||
rules, ok := CascadeMap[table]
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
for _, rule := range rules {
|
||||
key := rule.Table + ":" + strings.Join(ids, ",")
|
||||
if visited[key] {
|
||||
continue
|
||||
}
|
||||
visited[key] = true
|
||||
|
||||
var records []map[string]interface{}
|
||||
if err := tx.Table(rule.Table).Where(rule.FKColumn+" IN ?", ids).Find(&records).Error; err != nil {
|
||||
continue
|
||||
}
|
||||
if len(records) > 0 {
|
||||
groups = append(groups, CascadeGroup{
|
||||
Table: rule.Table,
|
||||
FKColumn: rule.FKColumn,
|
||||
DeleteRule: rule.DeleteRule,
|
||||
Records: records,
|
||||
})
|
||||
childIDs := extractIDs(records, "id")
|
||||
walk(rule.Table, childIDs)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
walk(tableName, []string{recordID})
|
||||
return groups, nil
|
||||
}
|
||||
|
||||
func extractIDs(records []map[string]interface{}, key string) []string {
|
||||
ids := make([]string, 0, len(records))
|
||||
for _, r := range records {
|
||||
if v, ok := r[key]; ok && v != nil {
|
||||
switch id := v.(type) {
|
||||
case string:
|
||||
ids = append(ids, id)
|
||||
case float64:
|
||||
ids = append(ids, fmt.Sprintf("%.0f", id))
|
||||
}
|
||||
}
|
||||
}
|
||||
return ids
|
||||
}
|
||||
|
||||
func toJSON(v interface{}) *string {
|
||||
if v == nil {
|
||||
return nil
|
||||
}
|
||||
b, err := json.Marshal(v)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
s := string(b)
|
||||
return &s
|
||||
}
|
||||
|
||||
func (u *ActivityLogUsecase) LogCreate(tableName string, record interface{}, merchantID *string) {
|
||||
db := u.Helper.GetDB("master")
|
||||
log := domain.ActivityLog{
|
||||
TargetTable: tableName,
|
||||
RecordID: extractRecordID(record),
|
||||
Action: "CREATE",
|
||||
NewData: toJSON(record),
|
||||
UserID: u.AuthUser.ID,
|
||||
UserName: u.getDisplayName(),
|
||||
MerchantID: merchantID,
|
||||
CreatedOn: timePtr(time.Now()),
|
||||
}
|
||||
db.Create(&log)
|
||||
}
|
||||
|
||||
func (u *ActivityLogUsecase) LogUpdate(tableName string, oldData, newData interface{}, merchantID *string) {
|
||||
db := u.Helper.GetDB("master")
|
||||
log := domain.ActivityLog{
|
||||
TargetTable: tableName,
|
||||
RecordID: extractRecordID(oldData),
|
||||
Action: "UPDATE",
|
||||
OldData: toJSON(oldData),
|
||||
NewData: toJSON(newData),
|
||||
UserID: u.AuthUser.ID,
|
||||
UserName: u.getDisplayName(),
|
||||
MerchantID: merchantID,
|
||||
CreatedOn: timePtr(time.Now()),
|
||||
}
|
||||
db.Create(&log)
|
||||
}
|
||||
|
||||
func (u *ActivityLogUsecase) LogDelete(tableName string, recordID string, oldData interface{}, merchantID *string) {
|
||||
db := u.Helper.GetDB("master")
|
||||
|
||||
var cascadeData []CascadeGroup
|
||||
err := db.Transaction(func(tx *gorm.DB) error {
|
||||
var err error
|
||||
cascadeData, err = CaptureCascade(tx, tableName, recordID)
|
||||
return err
|
||||
})
|
||||
if err != nil {
|
||||
u.Helper.Log().Error("failed to capture cascade", zap.Error(err))
|
||||
cascadeData = []CascadeGroup{}
|
||||
}
|
||||
|
||||
log := domain.ActivityLog{
|
||||
TargetTable: tableName,
|
||||
RecordID: recordID,
|
||||
Action: "DELETE",
|
||||
OldData: toJSON(oldData),
|
||||
CascadeData: toJSON(cascadeData),
|
||||
UserID: u.AuthUser.ID,
|
||||
UserName: u.getDisplayName(),
|
||||
MerchantID: merchantID,
|
||||
CreatedOn: timePtr(time.Now()),
|
||||
}
|
||||
db.Create(&log)
|
||||
}
|
||||
|
||||
func (u *ActivityLogUsecase) GetAll(filter dto.ActivityLogFilterRequest) ([]dto.ActivityLogResponse, int64, error) {
|
||||
var logs []domain.ActivityLog
|
||||
var total int64
|
||||
|
||||
db := u.Helper.GetDB("slave")
|
||||
tx := db.Model(&logs)
|
||||
|
||||
if filter.TableName != "" {
|
||||
tx = tx.Where("table_name = ?", filter.TableName)
|
||||
}
|
||||
if filter.RecordID != "" {
|
||||
tx = tx.Where("record_id = ?", filter.RecordID)
|
||||
}
|
||||
if filter.Action != "" {
|
||||
tx = tx.Where("action = ?", filter.Action)
|
||||
}
|
||||
if filter.UserID != "" {
|
||||
tx = tx.Where("user_id = ?", filter.UserID)
|
||||
}
|
||||
if filter.MerchantID != "" {
|
||||
tx = tx.Where("merchant_id = ?", filter.MerchantID)
|
||||
}
|
||||
if filter.DateFrom != "" {
|
||||
tx = tx.Where("created_on >= ?", filter.DateFrom)
|
||||
}
|
||||
if filter.DateTo != "" {
|
||||
tx = tx.Where("created_on <= ?", filter.DateTo)
|
||||
}
|
||||
|
||||
tx.Count(&total)
|
||||
tx.Order("created_on DESC")
|
||||
if err := tx.Find(&logs).Error; err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
|
||||
responses := make([]dto.ActivityLogResponse, 0, len(logs))
|
||||
for _, l := range logs {
|
||||
responses = append(responses, toActivityLogResponse(l))
|
||||
}
|
||||
return responses, total, nil
|
||||
}
|
||||
|
||||
func (u *ActivityLogUsecase) GetList(req dto.DataTableRequest) (dto.DataTableResponse, error) {
|
||||
db := u.Helper.GetDB("slave")
|
||||
tx := db.Table("activity_log")
|
||||
dt := datatable.NewDatatable(tx, req)
|
||||
coldef := make([]dto.DataTableColDef, 0)
|
||||
coldef = append(coldef, dto.DataTableColDef{Field: "activity_log.table_name", Alias: "table_name"})
|
||||
coldef = append(coldef, dto.DataTableColDef{Field: "activity_log.record_id", Alias: "record_id"})
|
||||
coldef = append(coldef, dto.DataTableColDef{Field: "activity_log.action", Alias: "action"})
|
||||
coldef = append(coldef, dto.DataTableColDef{Field: "activity_log.user_id", Alias: "user_id"})
|
||||
coldef = append(coldef, dto.DataTableColDef{Field: "activity_log.user_name", Alias: "user_name"})
|
||||
coldef = append(coldef, dto.DataTableColDef{Field: "activity_log.id", Alias: "id"})
|
||||
return dt.Render(coldef), nil
|
||||
}
|
||||
|
||||
func (u *ActivityLogUsecase) GetByID(id string) (dto.ActivityLogResponse, error) {
|
||||
var log domain.ActivityLog
|
||||
db := u.Helper.GetDB("slave")
|
||||
if err := db.Where("id = ?", id).First(&log).Error; err != nil {
|
||||
return dto.ActivityLogResponse{}, err
|
||||
}
|
||||
return toActivityLogResponse(log), nil
|
||||
}
|
||||
|
||||
func (u *ActivityLogUsecase) Revert(logID string) error {
|
||||
db := u.Helper.GetDB("master")
|
||||
|
||||
var log domain.ActivityLog
|
||||
if err := db.Where("id = ?", logID).First(&log).Error; err != nil {
|
||||
return fmt.Errorf("activity log not found")
|
||||
}
|
||||
|
||||
switch log.Action {
|
||||
case "CREATE":
|
||||
return u.revertCreate(db, log)
|
||||
case "UPDATE":
|
||||
return u.revertUpdate(db, log)
|
||||
case "DELETE":
|
||||
return u.revertDelete(db, log)
|
||||
default:
|
||||
return fmt.Errorf("unsupported action: %s", log.Action)
|
||||
}
|
||||
}
|
||||
|
||||
func (u *ActivityLogUsecase) revertCreate(db *gorm.DB, log domain.ActivityLog) error {
|
||||
return db.Transaction(func(tx *gorm.DB) error {
|
||||
if err := tx.Exec("DELETE FROM "+log.TargetTable+" WHERE id = ?", log.RecordID).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
u.logRevert("CREATE", log)
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
func (u *ActivityLogUsecase) revertUpdate(db *gorm.DB, log domain.ActivityLog) error {
|
||||
return db.Transaction(func(tx *gorm.DB) error {
|
||||
if log.OldData == nil {
|
||||
return fmt.Errorf("no old data to revert")
|
||||
}
|
||||
|
||||
var oldRecord map[string]interface{}
|
||||
if err := json.Unmarshal([]byte(*log.OldData), &oldRecord); err != nil {
|
||||
return fmt.Errorf("failed to parse old data: %w", err)
|
||||
}
|
||||
|
||||
cleaned := cleanRecordMap(oldRecord)
|
||||
delete(cleaned, "created_on")
|
||||
delete(cleaned, "created_by")
|
||||
|
||||
if err := tx.Table(log.TargetTable).Where("id = ?", log.RecordID).Updates(cleaned).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
u.logRevert("UPDATE", log)
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
func (u *ActivityLogUsecase) revertDelete(db *gorm.DB, log domain.ActivityLog) error {
|
||||
return db.Transaction(func(tx *gorm.DB) error {
|
||||
var cascadeGroups []CascadeGroup
|
||||
if log.CascadeData != nil {
|
||||
if err := json.Unmarshal([]byte(*log.CascadeData), &cascadeGroups); err != nil {
|
||||
return fmt.Errorf("failed to parse cascade data: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
for i := len(cascadeGroups) - 1; i >= 0; i-- {
|
||||
group := cascadeGroups[i]
|
||||
for _, record := range group.Records {
|
||||
cleaned := cleanRecordMap(record)
|
||||
tx.Table(group.Table).Create(cleaned)
|
||||
}
|
||||
}
|
||||
|
||||
if log.OldData != nil {
|
||||
var mainRecord map[string]interface{}
|
||||
if err := json.Unmarshal([]byte(*log.OldData), &mainRecord); err == nil {
|
||||
cleaned := cleanRecordMap(mainRecord)
|
||||
tx.Table(log.TargetTable).Create(cleaned)
|
||||
}
|
||||
}
|
||||
|
||||
u.logRevert("DELETE", log)
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
func (u *ActivityLogUsecase) logRevert(originalAction string, originalLog domain.ActivityLog) {
|
||||
db := u.Helper.GetDB("master")
|
||||
revertLog := domain.ActivityLog{
|
||||
TargetTable: originalLog.TargetTable,
|
||||
RecordID: originalLog.RecordID,
|
||||
Action: "REVERT",
|
||||
OldData: toJSON(fmt.Sprintf("Reverted %s action (log_id: %s)", originalAction, originalLog.ID)),
|
||||
UserID: u.AuthUser.ID,
|
||||
UserName: u.getDisplayName(),
|
||||
MerchantID: originalLog.MerchantID,
|
||||
CreatedOn: timePtr(time.Now()),
|
||||
}
|
||||
db.Create(&revertLog)
|
||||
}
|
||||
|
||||
func (u *ActivityLogUsecase) getDisplayName() string {
|
||||
if u.AuthUser.NickName != nil && *u.AuthUser.NickName != "" {
|
||||
return *u.AuthUser.NickName
|
||||
}
|
||||
if u.AuthUser.Email != nil {
|
||||
return *u.AuthUser.Email
|
||||
}
|
||||
return u.AuthUser.ID
|
||||
}
|
||||
|
||||
func extractRecordID(record interface{}) string {
|
||||
switch v := record.(type) {
|
||||
case map[string]interface{}:
|
||||
if id, ok := v["id"].(string); ok {
|
||||
return id
|
||||
}
|
||||
case domain.Province:
|
||||
return v.ID
|
||||
case domain.City:
|
||||
return v.ID
|
||||
case domain.District:
|
||||
return v.ID
|
||||
case domain.Subdistrict:
|
||||
return v.ID
|
||||
case domain.PostalCode:
|
||||
return v.ID
|
||||
case domain.CostComponent:
|
||||
return v.ID
|
||||
case domain.PackageType:
|
||||
return v.ID
|
||||
case domain.Moda:
|
||||
return v.ID
|
||||
case domain.BasicPricing:
|
||||
return v.ID
|
||||
}
|
||||
|
||||
b, err := json.Marshal(record)
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
var m map[string]interface{}
|
||||
if err := json.Unmarshal(b, &m); err != nil {
|
||||
return ""
|
||||
}
|
||||
if id, ok := m["id"].(string); ok {
|
||||
return id
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func timePtr(t time.Time) *time.Time {
|
||||
return &t
|
||||
}
|
||||
|
||||
func toActivityLogResponse(log domain.ActivityLog) dto.ActivityLogResponse {
|
||||
resp := dto.ActivityLogResponse{
|
||||
ID: log.ID,
|
||||
TableName: log.TargetTable,
|
||||
RecordID: log.RecordID,
|
||||
Action: log.Action,
|
||||
OldData: log.OldData,
|
||||
NewData: log.NewData,
|
||||
CascadeData: log.CascadeData,
|
||||
UserID: log.UserID,
|
||||
UserName: log.UserName,
|
||||
MerchantID: log.MerchantID,
|
||||
}
|
||||
if log.CreatedOn != nil {
|
||||
s := log.CreatedOn.Format("2006-01-02 15:04:05")
|
||||
resp.CreatedOn = &s
|
||||
}
|
||||
if log.CascadeData != nil {
|
||||
var groups []CascadeGroup
|
||||
if err := json.Unmarshal([]byte(*log.CascadeData), &groups); err == nil {
|
||||
count := 0
|
||||
for _, g := range groups {
|
||||
count += len(g.Records)
|
||||
}
|
||||
resp.CascadeCount = count
|
||||
}
|
||||
}
|
||||
return resp
|
||||
}
|
||||
|
||||
func cleanRecordMap(record map[string]interface{}) map[string]interface{} {
|
||||
cleaned := make(map[string]interface{})
|
||||
for k, v := range record {
|
||||
if v == nil {
|
||||
continue
|
||||
}
|
||||
switch v.(type) {
|
||||
case map[string]interface{}, []interface{}:
|
||||
continue
|
||||
}
|
||||
cleaned[k] = v
|
||||
}
|
||||
return cleaned
|
||||
}
|
||||
@ -44,17 +44,20 @@ func (u *AuthUsecase) Login(email string, password string) (token string, err er
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
//
|
||||
key := fmt.Sprintf("session_login:%v:*", v.ID)
|
||||
iter := u.Helper.GetRedis("master").Scan(ctx, 0, key, 1000).Iterator()
|
||||
for iter.Next(ctx) {
|
||||
keys := iter.Val()
|
||||
keys_ex := strings.Split(keys, ":")
|
||||
//change to del if using single login
|
||||
if keys_ex[1] == v.ID {
|
||||
cachedToken := keys_ex[2]
|
||||
_, verifyErr := secretJwt.VerifyToken(cachedToken)
|
||||
if verifyErr == nil {
|
||||
u.Helper.GetRedis("master").Expire(ctx, keys, time.Duration(t)*time.Second)
|
||||
return keys_ex[2], nil
|
||||
return cachedToken, nil
|
||||
}
|
||||
u.Helper.GetRedis("master").Del(ctx, keys)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -19,6 +19,7 @@ type BasicPricingUsecaseInterface interface {
|
||||
Create(req dto.CreateBasicPricingRequest, createdBy string, merchantid *string) (dto.CreateBasicPricingResponse, error)
|
||||
Update(id string, req dto.CreateBasicPricingRequest, updatedBy string) (dto.CreateBasicPricingResponse, error)
|
||||
Delete(id string) error
|
||||
GetMatch(id string) *dto.CreateBasicPricingResponse
|
||||
}
|
||||
|
||||
type BasicPricingUsecase struct {
|
||||
@ -77,7 +78,29 @@ func (u *BasicPricingUsecase) toResponse(pricing domain.BasicPricing, components
|
||||
}
|
||||
return resp
|
||||
}
|
||||
func (u *BasicPricingUsecase) GetMatch(id string) *dto.CreateBasicPricingResponse {
|
||||
var pricings domain.BasicPricing
|
||||
|
||||
db := u.Helper.GetDB("slave")
|
||||
tx := db.Model(&pricings).Where("basic_pricing.id = ?", id)
|
||||
if u.AuthUser.UsersRole_Relation == nil || u.AuthUser.UsersRole_Relation.RoleKey != "SPM" {
|
||||
tx = tx.Where("basic_pricing.merchant_id = ?", u.AuthUser.MerchantID)
|
||||
}
|
||||
|
||||
if err := tx.First(&pricings).Error; err != nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
pricingIDs := make([]string, 0)
|
||||
pricingIDs = append(pricingIDs, pricings.ID)
|
||||
componentsMap, err := u.loadComponents(pricingIDs)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
responses := u.toResponse(pricings, componentsMap[pricings.ID])
|
||||
return &responses
|
||||
}
|
||||
func (u *BasicPricingUsecase) GetAll(filter dto.BasicPricingFilterAllRequest) ([]dto.CreateBasicPricingResponse, int64, error) {
|
||||
var pricings []domain.BasicPricing
|
||||
var total int64
|
||||
@ -85,7 +108,7 @@ func (u *BasicPricingUsecase) GetAll(filter dto.BasicPricingFilterAllRequest) ([
|
||||
db := u.Helper.GetDB("slave")
|
||||
tx := db.Model(&pricings)
|
||||
if u.AuthUser.UsersRole_Relation == nil || u.AuthUser.UsersRole_Relation.RoleKey != "SPM" {
|
||||
tx = tx.Where(db.Where("merchant_id IS NULL").Or("merchant_id=?", u.AuthUser.MerchantID))
|
||||
tx = tx.Where("merchant_id=?", u.AuthUser.MerchantID)
|
||||
}
|
||||
v := reflect.ValueOf(filter)
|
||||
t := reflect.TypeOf(filter)
|
||||
@ -129,7 +152,7 @@ func (u *BasicPricingUsecase) GetList(req dto.DataTableRequest) (dto.DataTableRe
|
||||
Joins("LEFT JOIN city AS cd ON basic_pricing.city_destination_id=cd.id").
|
||||
Joins("LEFT JOIN merchant ON basic_pricing.merchant_id=merchant.id")
|
||||
if u.AuthUser.UsersRole_Relation == nil || u.AuthUser.UsersRole_Relation.RoleKey != "SPM" {
|
||||
tx = tx.Where("basic_pricing.merchant_id IS NULL OR basic_pricing.merchant_id=?", u.AuthUser.MerchantID)
|
||||
tx = tx.Where("basic_pricing.merchant_id=?", u.AuthUser.MerchantID)
|
||||
}
|
||||
dt := datatable.NewDatatable(tx, req)
|
||||
coldef := make([]dto.DataTableColDef, 0)
|
||||
@ -209,12 +232,15 @@ func (u *BasicPricingUsecase) Create(req dto.CreateBasicPricingRequest, createdB
|
||||
if err != nil {
|
||||
return dto.CreateBasicPricingResponse{}, err
|
||||
}
|
||||
logUsecase := NewActivityLogUsecase(u.Helper, u.AuthUser)
|
||||
logUsecase.LogCreate("basic_pricing", pricing, merchantid)
|
||||
return u.toResponse(pricing, savedComponents), nil
|
||||
}
|
||||
|
||||
func (u *BasicPricingUsecase) Update(id string, req dto.CreateBasicPricingRequest, updatedBy string) (dto.CreateBasicPricingResponse, error) {
|
||||
db := u.Helper.GetDB("master")
|
||||
var pricing domain.BasicPricing
|
||||
var oldPricing domain.BasicPricing
|
||||
var savedComponents []domain.BasicPricingComponent
|
||||
|
||||
err := db.Transaction(func(tx *gorm.DB) error {
|
||||
@ -225,6 +251,7 @@ func (u *BasicPricingUsecase) Update(id string, req dto.CreateBasicPricingReques
|
||||
if err := q.Where("id = ?", id).First(&pricing).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
oldPricing = pricing
|
||||
now := time.Now()
|
||||
pricing.ProvinceSourceID = strPtr(req.ProvinceSourceID)
|
||||
pricing.CitySourceID = strPtr(req.CitySourceID)
|
||||
@ -267,6 +294,12 @@ func (u *BasicPricingUsecase) Update(id string, req dto.CreateBasicPricingReques
|
||||
if err != nil {
|
||||
return dto.CreateBasicPricingResponse{}, err
|
||||
}
|
||||
var merchantID *string
|
||||
if u.AuthUser.UsersRole_Relation == nil || u.AuthUser.UsersRole_Relation.RoleKey != "SPM" {
|
||||
merchantID = u.AuthUser.MerchantID
|
||||
}
|
||||
logUsecase := NewActivityLogUsecase(u.Helper, u.AuthUser)
|
||||
logUsecase.LogUpdate("basic_pricing", oldPricing, pricing, merchantID)
|
||||
return u.toResponse(pricing, savedComponents), nil
|
||||
}
|
||||
|
||||
@ -281,6 +314,12 @@ func (u *BasicPricingUsecase) Delete(id string) error {
|
||||
if err := q.Where("id = ?", id).First(&pricing).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
var merchantID *string
|
||||
if u.AuthUser.UsersRole_Relation == nil || u.AuthUser.UsersRole_Relation.RoleKey != "SPM" {
|
||||
merchantID = u.AuthUser.MerchantID
|
||||
}
|
||||
logUsecase := NewActivityLogUsecase(u.Helper, u.AuthUser)
|
||||
logUsecase.LogDelete("basic_pricing", id, pricing, merchantID)
|
||||
if err := tx.Where("basic_pricing_id = ?", id).Delete(&domain.BasicPricingComponent{}).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@ -125,11 +125,14 @@ func (u *CityUsecase) Create(name string, provinceID string, port string, create
|
||||
if err != nil {
|
||||
return domain.City{}, err
|
||||
}
|
||||
logUsecase := NewActivityLogUsecase(u.Helper, u.AuthUser)
|
||||
logUsecase.LogCreate("city", city, merchantid)
|
||||
return city, nil
|
||||
}
|
||||
|
||||
func (u *CityUsecase) Update(id string, name string, provinceID string, port string, updatedBy string) (domain.City, error) {
|
||||
var city domain.City
|
||||
var oldCity domain.City
|
||||
db := u.Helper.GetDB("master")
|
||||
err := db.Transaction(func(tx *gorm.DB) error {
|
||||
q := tx
|
||||
@ -139,6 +142,7 @@ func (u *CityUsecase) Update(id string, name string, provinceID string, port str
|
||||
if err := q.Where("id = ?", id).First(&city).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
oldCity = city
|
||||
now := time.Now()
|
||||
city.Name = &name
|
||||
city.ProvinceID = &provinceID
|
||||
@ -150,14 +154,31 @@ func (u *CityUsecase) Update(id string, name string, provinceID string, port str
|
||||
if err != nil {
|
||||
return domain.City{}, err
|
||||
}
|
||||
var merchantID *string
|
||||
if u.AuthUser.UsersRole_Relation == nil || u.AuthUser.UsersRole_Relation.RoleKey != "SPM" {
|
||||
merchantID = u.AuthUser.MerchantID
|
||||
}
|
||||
logUsecase := NewActivityLogUsecase(u.Helper, u.AuthUser)
|
||||
logUsecase.LogUpdate("city", oldCity, city, merchantID)
|
||||
return city, nil
|
||||
}
|
||||
|
||||
func (u *CityUsecase) Delete(id string) error {
|
||||
db := u.Helper.GetDB("master")
|
||||
var city domain.City
|
||||
q := db
|
||||
if u.AuthUser.UsersRole_Relation == nil || u.AuthUser.UsersRole_Relation.RoleKey != "SPM" {
|
||||
db = db.Where("merchant_id=?", u.AuthUser.MerchantID)
|
||||
q = db.Where("merchant_id=?", u.AuthUser.MerchantID)
|
||||
}
|
||||
if err := q.Where("id = ?", id).First(&city).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
var merchantID *string
|
||||
if u.AuthUser.UsersRole_Relation == nil || u.AuthUser.UsersRole_Relation.RoleKey != "SPM" {
|
||||
merchantID = u.AuthUser.MerchantID
|
||||
}
|
||||
logUsecase := NewActivityLogUsecase(u.Helper, u.AuthUser)
|
||||
logUsecase.LogDelete("city", id, city, merchantID)
|
||||
if err := db.Delete(&domain.City{}, "id = ?", id).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@ -148,11 +148,14 @@ func (u *CostComponentUsecase) Create(name string, code string, value string, co
|
||||
if err != nil {
|
||||
return domain.CostComponent{}, err
|
||||
}
|
||||
logUsecase := NewActivityLogUsecase(u.Helper, u.AuthUser)
|
||||
logUsecase.LogCreate("cost_component", component, merchantid)
|
||||
return component, nil
|
||||
}
|
||||
|
||||
func (u *CostComponentUsecase) Update(id string, name string, code string, value string, componentType int32, unitType int32, updatedBy string) (domain.CostComponent, error) {
|
||||
var component domain.CostComponent
|
||||
var oldComponent domain.CostComponent
|
||||
db := u.Helper.GetDB("master")
|
||||
err := db.Transaction(func(tx *gorm.DB) error {
|
||||
q := tx
|
||||
@ -162,6 +165,7 @@ func (u *CostComponentUsecase) Update(id string, name string, code string, value
|
||||
if err := q.Where("id = ?", id).First(&component).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
oldComponent = component
|
||||
now := time.Now()
|
||||
component.Name = &name
|
||||
component.Code = &code
|
||||
@ -175,14 +179,31 @@ func (u *CostComponentUsecase) Update(id string, name string, code string, value
|
||||
if err != nil {
|
||||
return domain.CostComponent{}, err
|
||||
}
|
||||
var merchantID *string
|
||||
if u.AuthUser.UsersRole_Relation == nil || u.AuthUser.UsersRole_Relation.RoleKey != "SPM" {
|
||||
merchantID = u.AuthUser.MerchantID
|
||||
}
|
||||
logUsecase := NewActivityLogUsecase(u.Helper, u.AuthUser)
|
||||
logUsecase.LogUpdate("cost_component", oldComponent, component, merchantID)
|
||||
return component, nil
|
||||
}
|
||||
|
||||
func (u *CostComponentUsecase) Delete(id string) error {
|
||||
db := u.Helper.GetDB("master")
|
||||
var component domain.CostComponent
|
||||
q := db
|
||||
if u.AuthUser.UsersRole_Relation == nil || u.AuthUser.UsersRole_Relation.RoleKey != "SPM" {
|
||||
db = db.Where("merchant_id=?", u.AuthUser.MerchantID)
|
||||
q = db.Where("merchant_id=?", u.AuthUser.MerchantID)
|
||||
}
|
||||
if err := q.Where("id = ?", id).First(&component).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
var merchantID *string
|
||||
if u.AuthUser.UsersRole_Relation == nil || u.AuthUser.UsersRole_Relation.RoleKey != "SPM" {
|
||||
merchantID = u.AuthUser.MerchantID
|
||||
}
|
||||
logUsecase := NewActivityLogUsecase(u.Helper, u.AuthUser)
|
||||
logUsecase.LogDelete("cost_component", id, component, merchantID)
|
||||
if err := db.Delete(&domain.CostComponent{}, "id = ?", id).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@ -134,11 +134,14 @@ func (u *DistrictUsecase) Create(name string, provinceID string, cityID string,
|
||||
if err != nil {
|
||||
return domain.District{}, err
|
||||
}
|
||||
logUsecase := NewActivityLogUsecase(u.Helper, u.AuthUser)
|
||||
logUsecase.LogCreate("district", district, merchantid)
|
||||
return district, nil
|
||||
}
|
||||
|
||||
func (u *DistrictUsecase) Update(id string, name string, provinceID string, cityID string, updatedBy string) (domain.District, error) {
|
||||
var district domain.District
|
||||
var oldDistrict domain.District
|
||||
db := u.Helper.GetDB("master")
|
||||
err := db.Transaction(func(tx *gorm.DB) error {
|
||||
q := tx
|
||||
@ -148,6 +151,7 @@ func (u *DistrictUsecase) Update(id string, name string, provinceID string, city
|
||||
if err := q.Where("id = ?", id).First(&district).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
oldDistrict = district
|
||||
now := time.Now()
|
||||
district.Name = &name
|
||||
district.ProvinceID = &provinceID
|
||||
@ -159,14 +163,31 @@ func (u *DistrictUsecase) Update(id string, name string, provinceID string, city
|
||||
if err != nil {
|
||||
return domain.District{}, err
|
||||
}
|
||||
var merchantID *string
|
||||
if u.AuthUser.UsersRole_Relation == nil || u.AuthUser.UsersRole_Relation.RoleKey != "SPM" {
|
||||
merchantID = u.AuthUser.MerchantID
|
||||
}
|
||||
logUsecase := NewActivityLogUsecase(u.Helper, u.AuthUser)
|
||||
logUsecase.LogUpdate("district", oldDistrict, district, merchantID)
|
||||
return district, nil
|
||||
}
|
||||
|
||||
func (u *DistrictUsecase) Delete(id string) error {
|
||||
db := u.Helper.GetDB("master")
|
||||
var district domain.District
|
||||
q := db
|
||||
if u.AuthUser.UsersRole_Relation == nil || u.AuthUser.UsersRole_Relation.RoleKey != "SPM" {
|
||||
db = db.Where("merchant_id=?", u.AuthUser.MerchantID)
|
||||
q = db.Where("merchant_id=?", u.AuthUser.MerchantID)
|
||||
}
|
||||
if err := q.Where("id = ?", id).First(&district).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
var merchantID *string
|
||||
if u.AuthUser.UsersRole_Relation == nil || u.AuthUser.UsersRole_Relation.RoleKey != "SPM" {
|
||||
merchantID = u.AuthUser.MerchantID
|
||||
}
|
||||
logUsecase := NewActivityLogUsecase(u.Helper, u.AuthUser)
|
||||
logUsecase.LogDelete("district", id, district, merchantID)
|
||||
if err := db.Delete(&domain.District{}, "id = ?", id).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
175
internal/usecases/moda.go
Normal file
175
internal/usecases/moda.go
Normal file
@ -0,0 +1,175 @@
|
||||
package usecases
|
||||
|
||||
import (
|
||||
"cargo-erp-backend/internal/domain"
|
||||
"cargo-erp-backend/internal/handlers/dto"
|
||||
"cargo-erp-backend/pkg/datatable"
|
||||
"cargo-erp-backend/pkg/helpers"
|
||||
"fmt"
|
||||
"reflect"
|
||||
"time"
|
||||
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
type ModaUsecaseInterface interface {
|
||||
GetAll(filter dto.ModaFilterAllRequest) ([]domain.Moda, int64, error)
|
||||
GetList(dto.DataTableRequest) (dto.DataTableResponse, error)
|
||||
GetByID(id string) (domain.Moda, error)
|
||||
Create(name string, createdBy string, merchantid *string) (domain.Moda, error)
|
||||
Update(id string, name string, updatedBy string) (domain.Moda, error)
|
||||
Delete(id string) error
|
||||
}
|
||||
|
||||
type ModaUsecase struct {
|
||||
Helper helpers.HelperInterface
|
||||
AuthUser domain.User
|
||||
}
|
||||
|
||||
func NewModaUsecase(helper helpers.HelperInterface, authUser domain.User) ModaUsecaseInterface {
|
||||
return &ModaUsecase{Helper: helper, AuthUser: authUser}
|
||||
}
|
||||
|
||||
func (u *ModaUsecase) GetAll(filter dto.ModaFilterAllRequest) ([]domain.Moda, int64, error) {
|
||||
var items []domain.Moda
|
||||
var total int64
|
||||
|
||||
db := u.Helper.GetDB("slave")
|
||||
tx := db.Model(&items)
|
||||
if u.AuthUser.UsersRole_Relation == nil || u.AuthUser.UsersRole_Relation.RoleKey != "SPM" {
|
||||
tx = tx.Where(db.Where("merchant_id IS NULL").Or("merchant_id=?", u.AuthUser.MerchantID))
|
||||
}
|
||||
v := reflect.ValueOf(filter)
|
||||
t := reflect.TypeOf(filter)
|
||||
|
||||
for i := 0; i < v.NumField(); i++ {
|
||||
if v.Field(i).String() != "" {
|
||||
tagKey := t.Field(i).Tag.Get("form")
|
||||
tx = tx.Where(fmt.Sprintf("%v=?", tagKey), v.Field(i))
|
||||
}
|
||||
}
|
||||
tx.Model(&domain.Moda{}).Count(&total)
|
||||
tx.Order("name ASC")
|
||||
if err := tx.Find(&items).Error; err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
return items, total, nil
|
||||
}
|
||||
|
||||
func (u *ModaUsecase) GetList(req dto.DataTableRequest) (dto.DataTableResponse, error) {
|
||||
var response dto.DataTableResponse
|
||||
db := u.Helper.GetDB("slave")
|
||||
tx := db.Table("moda").
|
||||
Joins("LEFT JOIN merchant ON moda.merchant_id=merchant.id")
|
||||
if u.AuthUser.UsersRole_Relation == nil || u.AuthUser.UsersRole_Relation.RoleKey != "SPM" {
|
||||
tx = tx.Where("moda.merchant_id IS NULL OR moda.merchant_id=?", u.AuthUser.MerchantID)
|
||||
}
|
||||
dt := datatable.NewDatatable(tx, req)
|
||||
coldef := make([]dto.DataTableColDef, 0)
|
||||
coldef = append(coldef, dto.DataTableColDef{
|
||||
Field: "moda.name",
|
||||
Alias: "name",
|
||||
})
|
||||
coldef = append(coldef, dto.DataTableColDef{
|
||||
Field: "merchant.id",
|
||||
Alias: "merchant_id",
|
||||
})
|
||||
coldef = append(coldef, dto.DataTableColDef{
|
||||
Field: "moda.id",
|
||||
Alias: "id",
|
||||
})
|
||||
|
||||
response = dt.Render(coldef)
|
||||
return response, nil
|
||||
}
|
||||
|
||||
func (u *ModaUsecase) GetByID(id string) (domain.Moda, error) {
|
||||
var item domain.Moda
|
||||
db := u.Helper.GetDB("slave")
|
||||
if u.AuthUser.UsersRole_Relation == nil || u.AuthUser.UsersRole_Relation.RoleKey != "SPM" {
|
||||
db = db.Where("merchant_id IS NULL OR merchant_id=?", u.AuthUser.MerchantID)
|
||||
}
|
||||
if err := db.Where("id = ?", id).First(&item).Error; err != nil {
|
||||
return domain.Moda{}, err
|
||||
}
|
||||
return item, nil
|
||||
}
|
||||
|
||||
func (u *ModaUsecase) Create(name string, createdBy string, merchantid *string) (domain.Moda, error) {
|
||||
now := time.Now()
|
||||
|
||||
db := u.Helper.GetDB("master")
|
||||
|
||||
var item domain.Moda
|
||||
err := db.Transaction(func(tx *gorm.DB) error {
|
||||
item = domain.Moda{
|
||||
Name: &name,
|
||||
MerchantID: merchantid,
|
||||
CreatedBy: &createdBy,
|
||||
CreatedOn: &now,
|
||||
UpdatedBy: &createdBy,
|
||||
UpdatedOn: &now,
|
||||
}
|
||||
|
||||
return tx.Create(&item).Error
|
||||
})
|
||||
if err != nil {
|
||||
return domain.Moda{}, err
|
||||
}
|
||||
logUsecase := NewActivityLogUsecase(u.Helper, u.AuthUser)
|
||||
logUsecase.LogCreate("moda", item, merchantid)
|
||||
return item, nil
|
||||
}
|
||||
|
||||
func (u *ModaUsecase) Update(id string, name string, updatedBy string) (domain.Moda, error) {
|
||||
var item domain.Moda
|
||||
var oldItem domain.Moda
|
||||
db := u.Helper.GetDB("master")
|
||||
err := db.Transaction(func(tx *gorm.DB) error {
|
||||
q := tx
|
||||
if u.AuthUser.UsersRole_Relation == nil || u.AuthUser.UsersRole_Relation.RoleKey != "SPM" {
|
||||
q = tx.Where("merchant_id=?", u.AuthUser.MerchantID)
|
||||
}
|
||||
if err := q.Where("id = ?", id).First(&item).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
oldItem = item
|
||||
now := time.Now()
|
||||
item.Name = &name
|
||||
item.UpdatedBy = &updatedBy
|
||||
item.UpdatedOn = &now
|
||||
return tx.Save(&item).Error
|
||||
})
|
||||
if err != nil {
|
||||
return domain.Moda{}, err
|
||||
}
|
||||
var merchantID *string
|
||||
if u.AuthUser.UsersRole_Relation == nil || u.AuthUser.UsersRole_Relation.RoleKey != "SPM" {
|
||||
merchantID = u.AuthUser.MerchantID
|
||||
}
|
||||
logUsecase := NewActivityLogUsecase(u.Helper, u.AuthUser)
|
||||
logUsecase.LogUpdate("moda", oldItem, item, merchantID)
|
||||
return item, nil
|
||||
}
|
||||
|
||||
func (u *ModaUsecase) Delete(id string) error {
|
||||
db := u.Helper.GetDB("master")
|
||||
var item domain.Moda
|
||||
q := db
|
||||
if u.AuthUser.UsersRole_Relation == nil || u.AuthUser.UsersRole_Relation.RoleKey != "SPM" {
|
||||
q = db.Where("merchant_id=?", u.AuthUser.MerchantID)
|
||||
}
|
||||
if err := q.Where("id = ?", id).First(&item).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
var merchantID *string
|
||||
if u.AuthUser.UsersRole_Relation == nil || u.AuthUser.UsersRole_Relation.RoleKey != "SPM" {
|
||||
merchantID = u.AuthUser.MerchantID
|
||||
}
|
||||
logUsecase := NewActivityLogUsecase(u.Helper, u.AuthUser)
|
||||
logUsecase.LogDelete("moda", id, item, merchantID)
|
||||
if err := db.Delete(&domain.Moda{}, "id = ?", id).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
175
internal/usecases/package_type.go
Normal file
175
internal/usecases/package_type.go
Normal file
@ -0,0 +1,175 @@
|
||||
package usecases
|
||||
|
||||
import (
|
||||
"cargo-erp-backend/internal/domain"
|
||||
"cargo-erp-backend/internal/handlers/dto"
|
||||
"cargo-erp-backend/pkg/datatable"
|
||||
"cargo-erp-backend/pkg/helpers"
|
||||
"fmt"
|
||||
"reflect"
|
||||
"time"
|
||||
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
type PackageTypeUsecaseInterface interface {
|
||||
GetAll(filter dto.PackageTypeFilterAllRequest) ([]domain.PackageType, int64, error)
|
||||
GetList(dto.DataTableRequest) (dto.DataTableResponse, error)
|
||||
GetByID(id string) (domain.PackageType, error)
|
||||
Create(name string, createdBy string, merchantid *string) (domain.PackageType, error)
|
||||
Update(id string, name string, updatedBy string) (domain.PackageType, error)
|
||||
Delete(id string) error
|
||||
}
|
||||
|
||||
type PackageTypeUsecase struct {
|
||||
Helper helpers.HelperInterface
|
||||
AuthUser domain.User
|
||||
}
|
||||
|
||||
func NewPackageTypeUsecase(helper helpers.HelperInterface, authUser domain.User) PackageTypeUsecaseInterface {
|
||||
return &PackageTypeUsecase{Helper: helper, AuthUser: authUser}
|
||||
}
|
||||
|
||||
func (u *PackageTypeUsecase) GetAll(filter dto.PackageTypeFilterAllRequest) ([]domain.PackageType, int64, error) {
|
||||
var items []domain.PackageType
|
||||
var total int64
|
||||
|
||||
db := u.Helper.GetDB("slave")
|
||||
tx := db.Model(&items)
|
||||
if u.AuthUser.UsersRole_Relation == nil || u.AuthUser.UsersRole_Relation.RoleKey != "SPM" {
|
||||
tx = tx.Where(db.Where("merchant_id IS NULL").Or("merchant_id=?", u.AuthUser.MerchantID))
|
||||
}
|
||||
v := reflect.ValueOf(filter)
|
||||
t := reflect.TypeOf(filter)
|
||||
|
||||
for i := 0; i < v.NumField(); i++ {
|
||||
if v.Field(i).String() != "" {
|
||||
tagKey := t.Field(i).Tag.Get("form")
|
||||
tx = tx.Where(fmt.Sprintf("%v=?", tagKey), v.Field(i))
|
||||
}
|
||||
}
|
||||
tx.Model(&domain.PackageType{}).Count(&total)
|
||||
tx.Order("name ASC")
|
||||
if err := tx.Find(&items).Error; err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
return items, total, nil
|
||||
}
|
||||
|
||||
func (u *PackageTypeUsecase) GetList(req dto.DataTableRequest) (dto.DataTableResponse, error) {
|
||||
var response dto.DataTableResponse
|
||||
db := u.Helper.GetDB("slave")
|
||||
tx := db.Table("package_type").
|
||||
Joins("LEFT JOIN merchant ON package_type.merchant_id=merchant.id")
|
||||
if u.AuthUser.UsersRole_Relation == nil || u.AuthUser.UsersRole_Relation.RoleKey != "SPM" {
|
||||
tx = tx.Where("package_type.merchant_id IS NULL OR package_type.merchant_id=?", u.AuthUser.MerchantID)
|
||||
}
|
||||
dt := datatable.NewDatatable(tx, req)
|
||||
coldef := make([]dto.DataTableColDef, 0)
|
||||
coldef = append(coldef, dto.DataTableColDef{
|
||||
Field: "package_type.name",
|
||||
Alias: "name",
|
||||
})
|
||||
coldef = append(coldef, dto.DataTableColDef{
|
||||
Field: "merchant.id",
|
||||
Alias: "merchant_id",
|
||||
})
|
||||
coldef = append(coldef, dto.DataTableColDef{
|
||||
Field: "package_type.id",
|
||||
Alias: "id",
|
||||
})
|
||||
|
||||
response = dt.Render(coldef)
|
||||
return response, nil
|
||||
}
|
||||
|
||||
func (u *PackageTypeUsecase) GetByID(id string) (domain.PackageType, error) {
|
||||
var item domain.PackageType
|
||||
db := u.Helper.GetDB("slave")
|
||||
if u.AuthUser.UsersRole_Relation == nil || u.AuthUser.UsersRole_Relation.RoleKey != "SPM" {
|
||||
db = db.Where("merchant_id IS NULL OR merchant_id=?", u.AuthUser.MerchantID)
|
||||
}
|
||||
if err := db.Where("id = ?", id).First(&item).Error; err != nil {
|
||||
return domain.PackageType{}, err
|
||||
}
|
||||
return item, nil
|
||||
}
|
||||
|
||||
func (u *PackageTypeUsecase) Create(name string, createdBy string, merchantid *string) (domain.PackageType, error) {
|
||||
now := time.Now()
|
||||
|
||||
db := u.Helper.GetDB("master")
|
||||
|
||||
var item domain.PackageType
|
||||
err := db.Transaction(func(tx *gorm.DB) error {
|
||||
item = domain.PackageType{
|
||||
Name: &name,
|
||||
MerchantID: merchantid,
|
||||
CreatedBy: &createdBy,
|
||||
CreatedOn: &now,
|
||||
UpdatedBy: &createdBy,
|
||||
UpdatedOn: &now,
|
||||
}
|
||||
|
||||
return tx.Create(&item).Error
|
||||
})
|
||||
if err != nil {
|
||||
return domain.PackageType{}, err
|
||||
}
|
||||
logUsecase := NewActivityLogUsecase(u.Helper, u.AuthUser)
|
||||
logUsecase.LogCreate("package_type", item, merchantid)
|
||||
return item, nil
|
||||
}
|
||||
|
||||
func (u *PackageTypeUsecase) Update(id string, name string, updatedBy string) (domain.PackageType, error) {
|
||||
var item domain.PackageType
|
||||
var oldItem domain.PackageType
|
||||
db := u.Helper.GetDB("master")
|
||||
err := db.Transaction(func(tx *gorm.DB) error {
|
||||
q := tx
|
||||
if u.AuthUser.UsersRole_Relation == nil || u.AuthUser.UsersRole_Relation.RoleKey != "SPM" {
|
||||
q = tx.Where("merchant_id=?", u.AuthUser.MerchantID)
|
||||
}
|
||||
if err := q.Where("id = ?", id).First(&item).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
oldItem = item
|
||||
now := time.Now()
|
||||
item.Name = &name
|
||||
item.UpdatedBy = &updatedBy
|
||||
item.UpdatedOn = &now
|
||||
return tx.Save(&item).Error
|
||||
})
|
||||
if err != nil {
|
||||
return domain.PackageType{}, err
|
||||
}
|
||||
var merchantID *string
|
||||
if u.AuthUser.UsersRole_Relation == nil || u.AuthUser.UsersRole_Relation.RoleKey != "SPM" {
|
||||
merchantID = u.AuthUser.MerchantID
|
||||
}
|
||||
logUsecase := NewActivityLogUsecase(u.Helper, u.AuthUser)
|
||||
logUsecase.LogUpdate("package_type", oldItem, item, merchantID)
|
||||
return item, nil
|
||||
}
|
||||
|
||||
func (u *PackageTypeUsecase) Delete(id string) error {
|
||||
db := u.Helper.GetDB("master")
|
||||
var item domain.PackageType
|
||||
q := db
|
||||
if u.AuthUser.UsersRole_Relation == nil || u.AuthUser.UsersRole_Relation.RoleKey != "SPM" {
|
||||
q = db.Where("merchant_id=?", u.AuthUser.MerchantID)
|
||||
}
|
||||
if err := q.Where("id = ?", id).First(&item).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
var merchantID *string
|
||||
if u.AuthUser.UsersRole_Relation == nil || u.AuthUser.UsersRole_Relation.RoleKey != "SPM" {
|
||||
merchantID = u.AuthUser.MerchantID
|
||||
}
|
||||
logUsecase := NewActivityLogUsecase(u.Helper, u.AuthUser)
|
||||
logUsecase.LogDelete("package_type", id, item, merchantID)
|
||||
if err := db.Delete(&domain.PackageType{}, "id = ?", id).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@ -147,18 +147,21 @@ func (u *PostalCodeUsecase) Create(postalCode string, provinceID string, cityID
|
||||
CreatedBy: &createdBy,
|
||||
CreatedOn: &now,
|
||||
UpdatedBy: &createdBy,
|
||||
UpdatedOn: &now,
|
||||
UpdatedOn: strPtr(now.Format("2006-01-02 15:04:05.999999-07:00")),
|
||||
}
|
||||
return tx.Create(&pc).Error
|
||||
})
|
||||
if err != nil {
|
||||
return domain.PostalCode{}, err
|
||||
}
|
||||
logUsecase := NewActivityLogUsecase(u.Helper, u.AuthUser)
|
||||
logUsecase.LogCreate("postal_code", pc, merchantid)
|
||||
return pc, nil
|
||||
}
|
||||
|
||||
func (u *PostalCodeUsecase) Update(id string, postalCode string, provinceID string, cityID string, districtID string, subdistrictID string, updatedBy string) (domain.PostalCode, error) {
|
||||
var pc domain.PostalCode
|
||||
var oldPC domain.PostalCode
|
||||
db := u.Helper.GetDB("master")
|
||||
err := db.Transaction(func(tx *gorm.DB) error {
|
||||
q := tx
|
||||
@ -168,6 +171,7 @@ func (u *PostalCodeUsecase) Update(id string, postalCode string, provinceID stri
|
||||
if err := q.Where("id = ?", id).First(&pc).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
oldPC = pc
|
||||
now := time.Now()
|
||||
pc.PostalCode = &postalCode
|
||||
pc.ProvinceID = &provinceID
|
||||
@ -175,20 +179,37 @@ func (u *PostalCodeUsecase) Update(id string, postalCode string, provinceID stri
|
||||
pc.DistrictID = &districtID
|
||||
pc.SubdistrictID = &subdistrictID
|
||||
pc.UpdatedBy = &updatedBy
|
||||
pc.UpdatedOn = &now
|
||||
pc.UpdatedOn = strPtr(now.Format("2006-01-02 15:04:05.999999-07:00"))
|
||||
return tx.Save(&pc).Error
|
||||
})
|
||||
if err != nil {
|
||||
return domain.PostalCode{}, err
|
||||
}
|
||||
var merchantID *string
|
||||
if u.AuthUser.UsersRole_Relation == nil || u.AuthUser.UsersRole_Relation.RoleKey != "SPM" {
|
||||
merchantID = u.AuthUser.MerchantID
|
||||
}
|
||||
logUsecase := NewActivityLogUsecase(u.Helper, u.AuthUser)
|
||||
logUsecase.LogUpdate("postal_code", oldPC, pc, merchantID)
|
||||
return pc, nil
|
||||
}
|
||||
|
||||
func (u *PostalCodeUsecase) Delete(id string) error {
|
||||
db := u.Helper.GetDB("master")
|
||||
var pc domain.PostalCode
|
||||
q := db
|
||||
if u.AuthUser.UsersRole_Relation == nil || u.AuthUser.UsersRole_Relation.RoleKey != "SPM" {
|
||||
db = db.Where("merchant_id=?", u.AuthUser.MerchantID)
|
||||
q = db.Where("merchant_id=?", u.AuthUser.MerchantID)
|
||||
}
|
||||
if err := q.Where("id = ?", id).First(&pc).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
var merchantID *string
|
||||
if u.AuthUser.UsersRole_Relation == nil || u.AuthUser.UsersRole_Relation.RoleKey != "SPM" {
|
||||
merchantID = u.AuthUser.MerchantID
|
||||
}
|
||||
logUsecase := NewActivityLogUsecase(u.Helper, u.AuthUser)
|
||||
logUsecase.LogDelete("postal_code", id, pc, merchantID)
|
||||
if err := db.Delete(&domain.PostalCode{}, "id = ?", id).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@ -121,11 +121,14 @@ func (u *ProvinceUsecase) Create(name string, createdBy string, merchantid *stri
|
||||
if err != nil {
|
||||
return domain.Province{}, err
|
||||
}
|
||||
logUsecase := NewActivityLogUsecase(u.Helper, u.AuthUser)
|
||||
logUsecase.LogCreate("province", province, merchantid)
|
||||
return province, nil
|
||||
}
|
||||
|
||||
func (u *ProvinceUsecase) Update(id string, name string, updatedBy string) (domain.Province, error) {
|
||||
var province domain.Province
|
||||
var oldProvince domain.Province
|
||||
db := u.Helper.GetDB("master")
|
||||
err := db.Transaction(func(tx *gorm.DB) error {
|
||||
q := tx
|
||||
@ -135,6 +138,7 @@ func (u *ProvinceUsecase) Update(id string, name string, updatedBy string) (doma
|
||||
if err := q.Where("id = ?", id).First(&province).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
oldProvince = province
|
||||
now := time.Now()
|
||||
province.Name = &name
|
||||
province.UpdatedBy = &updatedBy
|
||||
@ -144,14 +148,34 @@ func (u *ProvinceUsecase) Update(id string, name string, updatedBy string) (doma
|
||||
if err != nil {
|
||||
return domain.Province{}, err
|
||||
}
|
||||
var merchantID *string
|
||||
if u.AuthUser.UsersRole_Relation == nil || u.AuthUser.UsersRole_Relation.RoleKey != "SPM" {
|
||||
merchantID = u.AuthUser.MerchantID
|
||||
}
|
||||
logUsecase := NewActivityLogUsecase(u.Helper, u.AuthUser)
|
||||
logUsecase.LogUpdate("province", oldProvince, province, merchantID)
|
||||
return province, nil
|
||||
}
|
||||
|
||||
func (u *ProvinceUsecase) Delete(id string) error {
|
||||
db := u.Helper.GetDB("master")
|
||||
|
||||
var province domain.Province
|
||||
q := db
|
||||
if u.AuthUser.UsersRole_Relation == nil || u.AuthUser.UsersRole_Relation.RoleKey != "SPM" {
|
||||
db = db.Where("merchant_id=?", u.AuthUser.MerchantID)
|
||||
q = db.Where("merchant_id=?", u.AuthUser.MerchantID)
|
||||
}
|
||||
if err := q.Where("id = ?", id).First(&province).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var merchantID *string
|
||||
if u.AuthUser.UsersRole_Relation == nil || u.AuthUser.UsersRole_Relation.RoleKey != "SPM" {
|
||||
merchantID = u.AuthUser.MerchantID
|
||||
}
|
||||
logUsecase := NewActivityLogUsecase(u.Helper, u.AuthUser)
|
||||
logUsecase.LogDelete("province", id, province, merchantID)
|
||||
|
||||
if err := db.Delete(&domain.Province{}, "id = ?", id).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@ -144,11 +144,14 @@ func (u *SubdistrictUsecase) Create(name string, provinceID string, cityID strin
|
||||
if err != nil {
|
||||
return domain.Subdistrict{}, err
|
||||
}
|
||||
logUsecase := NewActivityLogUsecase(u.Helper, u.AuthUser)
|
||||
logUsecase.LogCreate("subdistrict", subdistrict, merchantid)
|
||||
return subdistrict, nil
|
||||
}
|
||||
|
||||
func (u *SubdistrictUsecase) Update(id string, name string, provinceID string, cityID string, districtID string, updatedBy string) (domain.Subdistrict, error) {
|
||||
var subdistrict domain.Subdistrict
|
||||
var oldSubdistrict domain.Subdistrict
|
||||
db := u.Helper.GetDB("master")
|
||||
err := db.Transaction(func(tx *gorm.DB) error {
|
||||
q := tx
|
||||
@ -158,6 +161,7 @@ func (u *SubdistrictUsecase) Update(id string, name string, provinceID string, c
|
||||
if err := q.Where("id = ?", id).First(&subdistrict).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
oldSubdistrict = subdistrict
|
||||
now := time.Now()
|
||||
subdistrict.Name = &name
|
||||
subdistrict.ProvinceID = &provinceID
|
||||
@ -170,14 +174,31 @@ func (u *SubdistrictUsecase) Update(id string, name string, provinceID string, c
|
||||
if err != nil {
|
||||
return domain.Subdistrict{}, err
|
||||
}
|
||||
var merchantID *string
|
||||
if u.AuthUser.UsersRole_Relation == nil || u.AuthUser.UsersRole_Relation.RoleKey != "SPM" {
|
||||
merchantID = u.AuthUser.MerchantID
|
||||
}
|
||||
logUsecase := NewActivityLogUsecase(u.Helper, u.AuthUser)
|
||||
logUsecase.LogUpdate("subdistrict", oldSubdistrict, subdistrict, merchantID)
|
||||
return subdistrict, nil
|
||||
}
|
||||
|
||||
func (u *SubdistrictUsecase) Delete(id string) error {
|
||||
db := u.Helper.GetDB("master")
|
||||
var subdistrict domain.Subdistrict
|
||||
q := db
|
||||
if u.AuthUser.UsersRole_Relation == nil || u.AuthUser.UsersRole_Relation.RoleKey != "SPM" {
|
||||
db = db.Where("merchant_id=?", u.AuthUser.MerchantID)
|
||||
q = db.Where("merchant_id=?", u.AuthUser.MerchantID)
|
||||
}
|
||||
if err := q.Where("id = ?", id).First(&subdistrict).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
var merchantID *string
|
||||
if u.AuthUser.UsersRole_Relation == nil || u.AuthUser.UsersRole_Relation.RoleKey != "SPM" {
|
||||
merchantID = u.AuthUser.MerchantID
|
||||
}
|
||||
logUsecase := NewActivityLogUsecase(u.Helper, u.AuthUser)
|
||||
logUsecase.LogDelete("subdistrict", id, subdistrict, merchantID)
|
||||
if err := db.Delete(&domain.Subdistrict{}, "id = ?", id).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
22
migrations/003_activity_log.sql
Normal file
22
migrations/003_activity_log.sql
Normal file
@ -0,0 +1,22 @@
|
||||
-- Activity Log table for user activity tracking and revert capability
|
||||
-- Run this migration before deploying the new code
|
||||
|
||||
CREATE TABLE IF NOT EXISTS activity_log (
|
||||
id character(26) PRIMARY KEY DEFAULT generate_ulid(),
|
||||
table_name character varying(100) NOT NULL,
|
||||
record_id character(26) NOT NULL,
|
||||
action character varying(20) NOT NULL,
|
||||
old_data jsonb,
|
||||
new_data jsonb,
|
||||
cascade_data jsonb,
|
||||
user_id character(26) NOT NULL,
|
||||
user_name character varying(255) NOT NULL,
|
||||
merchant_id character(26),
|
||||
created_on timestamp without time zone DEFAULT now()
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_activity_log_table_name ON activity_log(table_name);
|
||||
CREATE INDEX IF NOT EXISTS idx_activity_log_record_id ON activity_log(record_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_activity_log_user_id ON activity_log(user_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_activity_log_created_on ON activity_log(created_on);
|
||||
CREATE INDEX IF NOT EXISTS idx_activity_log_action ON activity_log(action);
|
||||
@ -1280,3 +1280,8 @@
|
||||
{"level":"info","ts":"2026-08-25T16:16:54.090+0700","caller":"database/database.go:63","msg":"DB Master Connected"}
|
||||
{"level":"info","ts":"2026-08-25T16:16:54.090+0700","caller":"database/database.go:76","msg":"Connect To Slave DB"}
|
||||
{"level":"info","ts":"2026-08-25T16:16:54.250+0700","caller":"database/database.go:86","msg":"DB Connection Done"}
|
||||
{"level":"info","ts":"2026-09-04T21:21:20.045+0700","caller":"database/database.go:55","msg":"Connect To Master DB"}
|
||||
{"level":"info","ts":"2026-09-04T21:21:20.135+0700","caller":"database/database.go:68","msg":"DB Master Connected"}
|
||||
{"level":"info","ts":"2026-09-04T21:21:20.135+0700","caller":"database/database.go:81","msg":"Connect To Slave DB"}
|
||||
{"level":"info","ts":"2026-09-04T21:21:20.232+0700","caller":"database/database.go:94","msg":"DB Connection Done"}
|
||||
{"level":"info","ts":"2026-09-04T21:21:20.362+0700","caller":"handlers/handlers.go:136","msg":"Starting Apps"}
|
||||
|
||||
@ -15418,3 +15418,9 @@
|
||||
{"level":"info","ts":"2026-08-25T16:17:15.380+0700","caller":"logger/database.go:40","msg":"generate query file: /Users/teguh/Documents/project/cargo/cargo-erp-deploy/app/backend/cmd/api/internal/domain/query_utils/subdistrict.gen.go"}
|
||||
{"level":"info","ts":"2026-08-25T16:17:15.392+0700","caller":"logger/database.go:40","msg":"generate query file: /Users/teguh/Documents/project/cargo/cargo-erp-deploy/app/backend/cmd/api/internal/domain/query_utils/gen.go"}
|
||||
{"level":"info","ts":"2026-08-25T16:17:15.392+0700","caller":"logger/database.go:40","msg":"Generate code done."}
|
||||
{"level":"info","ts":"2026-09-04T21:21:20.232+0700","caller":"database/redis.go:34","msg":"Parse config master"}
|
||||
{"level":"info","ts":"2026-09-04T21:21:20.234+0700","caller":"database/redis.go:49","msg":"Connecting to Redis master"}
|
||||
{"level":"info","ts":"2026-09-04T21:21:20.293+0700","caller":"database/redis.go:62","msg":"Connected"}
|
||||
{"level":"info","ts":"2026-09-04T21:21:20.293+0700","caller":"database/redis.go:34","msg":"Parse config slave"}
|
||||
{"level":"info","ts":"2026-09-04T21:21:20.293+0700","caller":"database/redis.go:49","msg":"Connecting to Redis slave"}
|
||||
{"level":"info","ts":"2026-09-04T21:21:20.361+0700","caller":"database/redis.go:62","msg":"Connected"}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user