Merge pull request #252 from weclapp-dev/master
Add a document type and additional fields
This commit is contained in:
@@ -46,13 +46,18 @@ public class Invoice implements IExportableTransaction {
|
||||
protected Date detailedDeliveryDateStart = null;
|
||||
protected Date detailedDeliveryPeriodEnd = null;
|
||||
|
||||
protected ArrayList<IZUGFeRDAllowanceCharge> Allowances = new ArrayList<IZUGFeRDAllowanceCharge>(),
|
||||
Charges = new ArrayList<IZUGFeRDAllowanceCharge>(), LogisticsServiceCharges = new ArrayList<IZUGFeRDAllowanceCharge>();
|
||||
protected ArrayList<IZUGFeRDAllowanceCharge> Allowances = new ArrayList<>(),
|
||||
Charges = new ArrayList<>(), LogisticsServiceCharges = new ArrayList<>();
|
||||
protected IZUGFeRDPaymentTerms paymentTerms = null;
|
||||
private Date invoiceReferencedIssueDate;
|
||||
private String specifiedProcuringProjectID = null;
|
||||
|
||||
|
||||
|
||||
private String specifiedProcuringProjectName = null;
|
||||
|
||||
public Invoice() {
|
||||
ZFItems = new ArrayList<IZUGFeRDExportableItem>();
|
||||
ZFItems = new ArrayList<>();
|
||||
setCurrency("EUR");
|
||||
}
|
||||
|
||||
@@ -246,7 +251,17 @@ public class Invoice implements IExportableTransaction {
|
||||
return invoiceReferencedDocumentID;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Override
|
||||
public Date getInvoiceReferencedIssueDate() {
|
||||
return invoiceReferencedIssueDate;
|
||||
}
|
||||
|
||||
public Invoice setInvoiceReferencedIssueDate(Date issueDate) {
|
||||
this.invoiceReferencedIssueDate = issueDate;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getBuyerOrderReferencedDocumentIssueDateTime() {
|
||||
return buyerOrderReferencedDocumentIssueDateTime;
|
||||
}
|
||||
@@ -637,4 +652,23 @@ public class Invoice implements IExportableTransaction {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSpecifiedProcuringProjectID() {
|
||||
return specifiedProcuringProjectID;
|
||||
}
|
||||
|
||||
public Invoice setSpecifiedProcuringProjectID(String specifiedProcuringProjectID) {
|
||||
this.specifiedProcuringProjectID = specifiedProcuringProjectID;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSpecifiedProcuringProjectName() {
|
||||
return specifiedProcuringProjectName;
|
||||
}
|
||||
|
||||
public Invoice setSpecifiedProcuringProjectName(String specifiedProcuringProjectName) {
|
||||
this.specifiedProcuringProjectName = specifiedProcuringProjectName;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -416,7 +416,7 @@ public interface IExportableTransaction {
|
||||
}
|
||||
|
||||
/**
|
||||
* get the ID of the prceding invoice, which is e.g. to be corrected if this is a correction
|
||||
* get the ID of the preceding invoice, which is e.g. to be corrected if this is a correction
|
||||
*
|
||||
* @return the ID of the document
|
||||
*/
|
||||
@@ -424,6 +424,7 @@ public interface IExportableTransaction {
|
||||
return null;
|
||||
}
|
||||
|
||||
default Date getInvoiceReferencedIssueDate(){return null;}
|
||||
/**
|
||||
* get the issue timestamp of the BuyerOrderReferencedDocument, which sits in the ApplicableSupplyChainTradeAgreement
|
||||
*
|
||||
@@ -488,4 +489,12 @@ public interface IExportableTransaction {
|
||||
default String[] getNotes() {
|
||||
return null;
|
||||
}
|
||||
|
||||
default String getSpecifiedProcuringProjectName(){
|
||||
return null;
|
||||
}
|
||||
|
||||
default String getSpecifiedProcuringProjectID(){
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
*/
|
||||
package org.mustangproject.ZUGFeRD;
|
||||
|
||||
import static org.mustangproject.ZUGFeRD.ZUGFeRDDateFormat.DATE;
|
||||
import static org.mustangproject.ZUGFeRD.model.TaxCategoryCodeTypeConstants.CATEGORY_CODES_WITH_EXEMPTION_REASON;
|
||||
|
||||
import java.io.IOException;
|
||||
@@ -46,8 +47,7 @@ public class ZUGFeRD1PullProvider extends ZUGFeRD2PullProvider implements IXMLPr
|
||||
|
||||
protected byte[] zugferdData;
|
||||
private String paymentTermsDescription;
|
||||
SimpleDateFormat zugferdDateFormat = new SimpleDateFormat("yyyyMMdd");
|
||||
protected Profile profile = Profiles.getByName("COMFORT", 1);
|
||||
protected Profile profile = Profiles.getByName("COMFORT", 1);
|
||||
|
||||
|
||||
/**
|
||||
@@ -169,8 +169,8 @@ public class ZUGFeRD1PullProvider extends ZUGFeRD2PullProvider implements IXMLPr
|
||||
+ " <ram:ID>" + XMLTools.encodeXML(trans.getNumber()) + "</ram:ID>\n"
|
||||
+ " <ram:Name>RECHNUNG</ram:Name>\n"
|
||||
+ " <ram:TypeCode>" + typecode + "</ram:TypeCode>\n"
|
||||
+ " <ram:IssueDateTime><udt:DateTimeString format=\"102\">"
|
||||
+ zugferdDateFormat.format(trans.getIssueDate()) + "</udt:DateTimeString></ram:IssueDateTime>\n" // date
|
||||
+ " <ram:IssueDateTime>"
|
||||
+ DATE.udtFormat(trans.getIssueDate()) + "</ram:IssueDateTime>\n" // date
|
||||
// format
|
||||
// was
|
||||
// 20130605
|
||||
@@ -225,8 +225,7 @@ public class ZUGFeRD1PullProvider extends ZUGFeRD2PullProvider implements IXMLPr
|
||||
+ " <ram:OccurrenceDateTime>";
|
||||
|
||||
if (trans.getDeliveryDate() != null) {
|
||||
xml += "<udt:DateTimeString format=\"102\">" + zugferdDateFormat.format(trans.getDeliveryDate())
|
||||
+ "</udt:DateTimeString>";
|
||||
xml += DATE.udtFormat(trans.getDeliveryDate());
|
||||
} else {
|
||||
throw new IllegalStateException("No delivery date provided");
|
||||
}
|
||||
@@ -292,9 +291,9 @@ public class ZUGFeRD1PullProvider extends ZUGFeRD2PullProvider implements IXMLPr
|
||||
}
|
||||
|
||||
if (hasDueDate && (trans.getDueDate() != null)) {
|
||||
xml = xml + " <ram:DueDateDateTime><udt:DateTimeString format=\"102\">" // $NON-NLS-2$
|
||||
+ zugferdDateFormat.format(trans.getDueDate())
|
||||
+ "</udt:DateTimeString></ram:DueDateDateTime>\n";// 20130704
|
||||
xml = xml + " <ram:DueDateDateTime>" // $NON-NLS-2$
|
||||
+ DATE.udtFormat(trans.getDueDate())
|
||||
+ "</ram:DueDateDateTime>\n";// 20130704
|
||||
|
||||
}
|
||||
xml = xml + " </ram:SpecifiedTradePaymentTerms>\n";
|
||||
@@ -440,8 +439,7 @@ public class ZUGFeRD1PullProvider extends ZUGFeRD2PullProvider implements IXMLPr
|
||||
paymentTermsXml += "<ram:Description>" + paymentTerms.getDescription() + "</ram:Description>";
|
||||
if (dueDate != null) {
|
||||
paymentTermsXml += "<ram:DueDateDateTime>";
|
||||
paymentTermsXml += "<udt:DateTimeString format=\"102\">"
|
||||
+ zugferdDateFormat.format(dueDate.getDate()) + "</udt:DateTimeString>";
|
||||
paymentTermsXml += DATE.udtFormat(dueDate) ;
|
||||
paymentTermsXml += "</ram:DueDateDateTime>";
|
||||
}
|
||||
|
||||
@@ -456,7 +454,7 @@ public class ZUGFeRD1PullProvider extends ZUGFeRD2PullProvider implements IXMLPr
|
||||
if (discountTerms.getBaseDate() != null) {
|
||||
final Date baseDate = discountTerms.getBaseDate();
|
||||
paymentTermsXml += "<ram:BasisDateTime>";
|
||||
paymentTermsXml += "<udt:DateTimeString format=\"102\">" + zugferdDateFormat.format(baseDate) + "</udt:DateTimeString>";
|
||||
paymentTermsXml += DATE.udtFormat(baseDate) ;
|
||||
paymentTermsXml += "</ram:BasisDateTime>";
|
||||
|
||||
paymentTermsXml += "<ram:BasisPeriodMeasure unitCode=\"" + discountTerms.getBasePeriodUnitCode() + "\">"
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
*/
|
||||
package org.mustangproject.ZUGFeRD;
|
||||
|
||||
import static org.mustangproject.ZUGFeRD.ZUGFeRDDateFormat.DATE;
|
||||
import static org.mustangproject.ZUGFeRD.model.DocumentCodeTypeConstants.CORRECTEDINVOICE;
|
||||
import static org.mustangproject.ZUGFeRD.model.TaxCategoryCodeTypeConstants.CATEGORY_CODES_WITH_EXEMPTION_REASON;
|
||||
|
||||
@@ -44,9 +45,7 @@ import org.mustangproject.XMLTools;
|
||||
|
||||
public class ZUGFeRD2PullProvider implements IXMLProvider {
|
||||
|
||||
//// MAIN CLASS
|
||||
protected SimpleDateFormat zugferdDateFormat = new SimpleDateFormat("yyyyMMdd");
|
||||
protected byte[] zugferdData;
|
||||
protected byte[] zugferdData;
|
||||
protected IExportableTransaction trans;
|
||||
protected TransactionCalculator calc;
|
||||
private String paymentTermsDescription;
|
||||
@@ -278,7 +277,8 @@ public class ZUGFeRD2PullProvider implements IXMLProvider {
|
||||
// xsi:schemaLocation=\"urn:un:unece:uncefact:data:standard:CrossIndustryInvoice:100
|
||||
// ../Schema/ZUGFeRD1p0.xsd\""
|
||||
+ " xmlns:ram=\"urn:un:unece:uncefact:data:standard:ReusableAggregateBusinessInformationEntity:100\""
|
||||
+ " xmlns:udt=\"urn:un:unece:uncefact:data:standard:UnqualifiedDataType:100\">\n"
|
||||
+ " xmlns:udt=\"urn:un:unece:uncefact:data:standard:UnqualifiedDataType:100\""
|
||||
+ " xmlns:qdt=\"urn:un:unece:uncefact:data:standard:QualifiedDataType:100\">\n"
|
||||
+ " <rsm:ExchangedDocumentContext>\n"
|
||||
// + "
|
||||
// <ram:TestIndicator><udt:Indicator>"+testBooleanStr+"</udt:Indicator></ram:TestIndicator>\n"
|
||||
@@ -292,8 +292,8 @@ public class ZUGFeRD2PullProvider implements IXMLProvider {
|
||||
// + " <ram:Name>RECHNUNG</ram:Name>\n"
|
||||
// + " <ram:TypeCode>380</ram:TypeCode>\n"
|
||||
+ " <ram:TypeCode>" + typecode + "</ram:TypeCode>\n"
|
||||
+ " <ram:IssueDateTime><udt:DateTimeString format=\"102\">"
|
||||
+ zugferdDateFormat.format(trans.getIssueDate()) + "</udt:DateTimeString></ram:IssueDateTime>\n" // date
|
||||
+ " <ram:IssueDateTime>"
|
||||
+ DATE.udtFormat(trans.getIssueDate()) + "</ram:IssueDateTime>\n" // date
|
||||
+ notes
|
||||
+ subjectNote
|
||||
+ rebateAgreement
|
||||
@@ -405,10 +405,10 @@ public class ZUGFeRD2PullProvider implements IXMLProvider {
|
||||
if ((currentItem.getDetailedDeliveryPeriodFrom() != null) || (currentItem.getDetailedDeliveryPeriodTo() != null)) {
|
||||
xml = xml + "<ram:BillingSpecifiedPeriod>";
|
||||
if (currentItem.getDetailedDeliveryPeriodFrom() != null) {
|
||||
xml = xml + "<ram:StartDateTime><udt:DateTimeString format='102'>" + zugferdDateFormat.format(currentItem.getDetailedDeliveryPeriodFrom()) + "</udt:DateTimeString></ram:StartDateTime>";
|
||||
xml = xml + "<ram:StartDateTime>" + DATE.udtFormat(currentItem.getDetailedDeliveryPeriodFrom()) + "</ram:StartDateTime>";
|
||||
}
|
||||
if (currentItem.getDetailedDeliveryPeriodTo() != null) {
|
||||
xml = xml + "<ram:EndDateTime><udt:DateTimeString format='102'>" + zugferdDateFormat.format(currentItem.getDetailedDeliveryPeriodTo()) + "</udt:DateTimeString></ram:EndDateTime>";
|
||||
xml = xml + "<ram:EndDateTime>" + DATE.udtFormat(currentItem.getDetailedDeliveryPeriodTo()) + "</ram:EndDateTime>";
|
||||
}
|
||||
xml = xml + "</ram:BillingSpecifiedPeriod>";
|
||||
|
||||
@@ -475,6 +475,15 @@ public class ZUGFeRD2PullProvider implements IXMLProvider {
|
||||
}
|
||||
}
|
||||
|
||||
if (trans.getSpecifiedProcuringProjectID() != null) {
|
||||
xml = xml + " <ram:SpecifiedProcuringProject>\n"
|
||||
+ " <ram:ID>"
|
||||
+ XMLTools.encodeXML(trans.getSpecifiedProcuringProjectID()) + "</ram:ID>\n";
|
||||
if(trans.getSpecifiedProcuringProjectName()!= null) {
|
||||
xml += " <ram:Name >" + XMLTools.encodeXML(trans.getSpecifiedProcuringProjectName()) + "</ram:Name>\n";
|
||||
}
|
||||
xml += " </ram:SpecifiedProcuringProject>\n";
|
||||
}
|
||||
xml = xml + " </ram:ApplicableHeaderTradeAgreement>\n"
|
||||
+ " <ram:ApplicableHeaderTradeDelivery>\n";
|
||||
if (this.trans.getDeliveryAddress() != null) {
|
||||
@@ -487,8 +496,7 @@ public class ZUGFeRD2PullProvider implements IXMLProvider {
|
||||
+ " <ram:OccurrenceDateTime>";
|
||||
|
||||
if (trans.getDeliveryDate() != null) {
|
||||
xml += "<udt:DateTimeString format=\"102\">" + zugferdDateFormat.format(trans.getDeliveryDate())
|
||||
+ "</udt:DateTimeString>";
|
||||
xml += DATE.udtFormat(trans.getDeliveryDate());
|
||||
} else {
|
||||
throw new IllegalStateException("No delivery date provided");
|
||||
}
|
||||
@@ -546,10 +554,10 @@ public class ZUGFeRD2PullProvider implements IXMLProvider {
|
||||
if ((trans.getDetailedDeliveryPeriodFrom() != null) || (trans.getDetailedDeliveryPeriodTo() != null)) {
|
||||
xml = xml + "<ram:BillingSpecifiedPeriod>";
|
||||
if (trans.getDetailedDeliveryPeriodFrom() != null) {
|
||||
xml = xml + "<ram:StartDateTime><udt:DateTimeString format='102'>" + zugferdDateFormat.format(trans.getDetailedDeliveryPeriodFrom()) + "</udt:DateTimeString></ram:StartDateTime>";
|
||||
xml = xml + "<ram:StartDateTime>" + DATE.udtFormat(trans.getDetailedDeliveryPeriodFrom()) + "</ram:StartDateTime>";
|
||||
}
|
||||
if (trans.getDetailedDeliveryPeriodTo() != null) {
|
||||
xml = xml + "<ram:EndDateTime><udt:DateTimeString format='102'>" + zugferdDateFormat.format(trans.getDetailedDeliveryPeriodTo()) + "</udt:DateTimeString></ram:EndDateTime>";
|
||||
xml = xml + "<ram:EndDateTime>" + DATE.udtFormat(trans.getDetailedDeliveryPeriodTo()) + "</ram:EndDateTime>";
|
||||
}
|
||||
xml = xml + "</ram:BillingSpecifiedPeriod>";
|
||||
|
||||
@@ -616,9 +624,9 @@ public class ZUGFeRD2PullProvider implements IXMLProvider {
|
||||
}
|
||||
|
||||
if (hasDueDate && (trans.getDueDate() != null)) {
|
||||
xml = xml + " <ram:DueDateDateTime><udt:DateTimeString format=\"102\">" // $NON-NLS-2$
|
||||
+ zugferdDateFormat.format(trans.getDueDate())
|
||||
+ "</udt:DateTimeString></ram:DueDateDateTime>\n";// 20130704
|
||||
xml = xml + " <ram:DueDateDateTime>" // $NON-NLS-2$
|
||||
+ DATE.udtFormat(trans.getDueDate())
|
||||
+ "</ram:DueDateDateTime>\n";// 20130704
|
||||
|
||||
}
|
||||
xml = xml + " </ram:SpecifiedTradePaymentTerms>\n";
|
||||
@@ -649,8 +657,13 @@ public class ZUGFeRD2PullProvider implements IXMLProvider {
|
||||
if (trans.getInvoiceReferencedDocumentID() != null) {
|
||||
xml = xml + " <ram:InvoiceReferencedDocument>\n"
|
||||
+ " <ram:IssuerAssignedID>"
|
||||
+ XMLTools.encodeXML(trans.getInvoiceReferencedDocumentID()) + "</ram:IssuerAssignedID>\n"
|
||||
+ " </ram:InvoiceReferencedDocument>\n";
|
||||
+ XMLTools.encodeXML(trans.getInvoiceReferencedDocumentID()) + "</ram:IssuerAssignedID>\n";
|
||||
if(trans.getInvoiceReferencedIssueDate()!= null){
|
||||
xml += "<ram:FormattedIssueDateTime>"
|
||||
+ DATE.qdtFormat(trans.getInvoiceReferencedIssueDate())
|
||||
+ "</ram:FormattedIssueDateTime>\n";
|
||||
}
|
||||
xml += " </ram:InvoiceReferencedDocument>\n";
|
||||
}
|
||||
|
||||
xml = xml + " </ram:ApplicableHeaderTradeSettlement>\n";
|
||||
@@ -698,8 +711,7 @@ public class ZUGFeRD2PullProvider implements IXMLProvider {
|
||||
paymentTermsXml += "<ram:Description>" + paymentTerms.getDescription() + "</ram:Description>";
|
||||
if (dueDate != null) {
|
||||
paymentTermsXml += "<ram:DueDateDateTime>";
|
||||
paymentTermsXml += "<udt:DateTimeString format=\"102\">"
|
||||
+ zugferdDateFormat.format(dueDate) + "</udt:DateTimeString>";
|
||||
paymentTermsXml += DATE.udtFormat(dueDate) ;
|
||||
paymentTermsXml += "</ram:DueDateDateTime>";
|
||||
}
|
||||
|
||||
@@ -714,7 +726,7 @@ public class ZUGFeRD2PullProvider implements IXMLProvider {
|
||||
if (discountTerms.getBaseDate() != null) {
|
||||
final Date baseDate = discountTerms.getBaseDate();
|
||||
paymentTermsXml += "<ram:BasisDateTime>";
|
||||
paymentTermsXml += "<udt:DateTimeString format=\"102\">" + zugferdDateFormat.format(baseDate) + "</udt:DateTimeString>";
|
||||
paymentTermsXml += DATE.udtFormat(baseDate);
|
||||
paymentTermsXml += "</ram:BasisDateTime>";
|
||||
|
||||
paymentTermsXml += "<ram:BasisPeriodMeasure unitCode=\"" + discountTerms.getBasePeriodUnitCode() + "\">"
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package org.mustangproject.ZUGFeRD;
|
||||
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
|
||||
import org.mustangproject.ZUGFeRD.model.DateTimeTypeConstants;
|
||||
|
||||
@@ -12,6 +13,8 @@ public enum ZUGFeRDDateFormat {
|
||||
|
||||
private String dateTimeType;
|
||||
private SimpleDateFormat formatter;
|
||||
private static final String QDT_FORMAT = "<qdt:DateTimeString format=\"%s\">%s</qdt:DateTimeString>";
|
||||
private static final String UDT_FORMAT = "<udt:DateTimeString format=\"%s\">%s</udt:DateTimeString>";
|
||||
|
||||
private ZUGFeRDDateFormat(String dateTimeType, SimpleDateFormat formatter) {
|
||||
this.dateTimeType = dateTimeType;
|
||||
@@ -25,4 +28,14 @@ public enum ZUGFeRDDateFormat {
|
||||
public SimpleDateFormat getFormatter() {
|
||||
return formatter;
|
||||
}
|
||||
|
||||
public String simpleFormat(Date date){
|
||||
return getFormatter().format(date);
|
||||
}
|
||||
public String qdtFormat(Date date){
|
||||
return String.format(QDT_FORMAT, getDateTimeType(), getFormatter().format(date));
|
||||
}
|
||||
public String udtFormat(Date date){
|
||||
return String.format(UDT_FORMAT, getDateTimeType(), getFormatter().format(date));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,4 +23,5 @@ public class DocumentCodeTypeConstants {
|
||||
public static final String CREDITNOTE = "381";
|
||||
public static final String DEBITNOTE = "84";
|
||||
public static final String CORRECTEDINVOICE = "384";
|
||||
public static final String PARTIAL_BILLING = "326";
|
||||
}
|
||||
|
||||
@@ -21,32 +21,32 @@
|
||||
*/
|
||||
package org.mustangproject.ZUGFeRD;
|
||||
|
||||
import org.junit.FixMethodOrder;
|
||||
import org.junit.runners.MethodSorters;
|
||||
import org.mustangproject.CII.CIIToUBL;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
import org.junit.FixMethodOrder;
|
||||
import org.junit.runners.MethodSorters;
|
||||
import org.mustangproject.CII.CIIToUBL;
|
||||
|
||||
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
|
||||
public class UBLTest extends ResourceCase {
|
||||
|
||||
public void testUBLBasic() {
|
||||
|
||||
// the writing part
|
||||
CIIToUBL c2u = new CIIToUBL();
|
||||
String sourceFilename = "factur-x.xml";
|
||||
File input = getResourceAsFile(sourceFilename);
|
||||
File expectedFile = getResourceAsFile("ubl-conv-ubl-output-factur-x.xml");
|
||||
final CIIToUBL c2u = new CIIToUBL();
|
||||
final String sourceFilename = "factur-x.xml";
|
||||
final File input = getResourceAsFile(sourceFilename);
|
||||
final File expectedFile = getResourceAsFile("ubl-conv-ubl-output-factur-x.xml");
|
||||
String expected = null;
|
||||
String result = null;
|
||||
try {
|
||||
File tempFile = File.createTempFile("ZUGFeRD-UBL-", "-test");
|
||||
final File tempFile = File.createTempFile("ZUGFeRD-UBL-", "-test");
|
||||
c2u.convert(input, tempFile);
|
||||
expected = ResourceUtilities.readFile(StandardCharsets.UTF_8, expectedFile.getAbsolutePath());
|
||||
result = ResourceUtilities.readFile(StandardCharsets.UTF_8, tempFile.getAbsolutePath());
|
||||
} catch (IOException e) {
|
||||
result = ResourceUtilities.readFile(StandardCharsets.UTF_8, tempFile.getAbsolutePath()).replaceAll("\r\n", "\n");
|
||||
} catch (final IOException e) {
|
||||
fail("Exception should not happen: "+e.getMessage());
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user